Overview
iStory offers flexible authentication with dual login methods: connect via Web3 wallet (MetaMask, Coinbase Wallet, etc.) or sign in with Google OAuth. You can also link both accounts for seamless access.No passwords required. Wallet users sign a cryptographic message, while Google users authenticate via OAuth 2.0.
Authentication Methods
Web3 Wallet Connection
Connect your Ethereum wallet to sign in without creating an account.Supported Wallets:
- MetaMask
- Coinbase Wallet
- WalletConnect-compatible wallets
- Rainbow Wallet
- Click Connect Wallet button in navigation
- Select your wallet provider from RainbowKit modal
- Approve connection in wallet popup
- Sign authentication message (no gas fee)
- You’re logged in! Session persists via JWT token
The signature message includes a one-time nonce that expires in 5 minutes, preventing replay attacks.
Google Sign-In
Use your existing Google account for quick access.Flow:
- Click Sign in with Google
- Choose your Google account
- Grant permissions (name, email, avatar)
- Redirected to your iStory dashboard
Link Both Accounts (Recommended)
Combine the convenience of Google login with Web3 wallet capabilities.To link accounts:
- Sign in with your primary method (wallet or Google)
- Navigate to Profile → Settings → Linked Accounts
- Click Link Google or Link Wallet
- Complete the signature verification
- Both methods are now linked to one unified profile
Authentication Flow Details
Wallet Authentication (components/AuthProvider.tsx:479-617)
How Wallet Login Works
How Wallet Login Works
Client-Side Flow:
- Connection Detection (
useEffectmonitorsisConnectedandaddress) - Session Check: Looks for stored JWT token in
localStorage(estory_wallet_token) - Nonce Request: If no token, fetches unique nonce from
/api/auth/nonce?address=0x... - Signature: User signs message via
signMessageAsync(no transaction) - Verification: Sends signature to
/api/auth/loginfor server-side verification - Token Storage: Receives JWT, stores in
localStorage, loads profile
- Nonce is UUID v4, stored server-side for 5 minutes
- Signature verified with
viem.verifyMessage - Nonce can only be used once (prevents replay attacks)
- JWT expires after 30 days, auto-refreshes on activity
Google OAuth Flow (components/AuthProvider.tsx:122-283)
How Google Sign-In Works
How Google Sign-In Works
Server-Side OAuth Flow:
- Initiation:
supabase.auth.signInWithOAuth({ provider: 'google' }) - Redirect: User authorizes on Google OAuth consent screen
- Callback:
/api/auth/callbackreceives authorization code - Token Exchange: Supabase exchanges code for access token
- Profile Creation: AuthProvider detects session, creates/updates user record
- Auto-Linking: If email matches existing wallet account, auto-links
- Check by Supabase auth user ID (returning users)
- Check by
google_id(account was merged, ID differs) - Check by email (same email = same person, auto-link)
- Create new Google-only user profile
Secure Account Linking (app/api/auth/link-google/route.ts)
Account Linking Security
Account Linking Security
Why linking requires signature:Linking a Google account to a wallet (or vice versa) requires proof of ownership via wallet signature. This prevents malicious actors from linking your Google account to their wallet.Secure Flow:
- User clicks Link Google in Profile settings
- User signs message:
"Link Google account to eStory wallet {address}\n\nTimestamp: {now}" - Server generates secure
linkingToken(UUID), stores in session - User completes Google OAuth flow
- Server verifies token + signature before linking accounts
- Token is single-use and expires after OAuth redirect
googleLinkingToken: Secure UUID tokengoogleLinkingUserId: Current user ID- Both cleared after linking completes or fails
Troubleshooting
Wallet signature keeps failing
Wallet signature keeps failing
Possible causes:
- You clicked “Reject” in MetaMask
- Nonce expired (5-minute window)
- Wallet is connected to wrong network
- Refresh the page
- Disconnect and reconnect wallet
- Switch to Base Sepolia testnet (chain ID: 84532)
- Try signing again within 5 minutes
Google sign-in redirects to error page
Google sign-in redirects to error page
Common issues:
- Third-party cookies blocked in browser
- Ad blocker interfering with OAuth popup
- Redirect URL not whitelisted
- Enable third-party cookies for
supabase.codomain - Disable ad blockers temporarily
- Try in incognito/private browsing mode
- Clear browser cache and retry
Can't link accounts - 'Already linked' error
Can't link accounts - 'Already linked' error
Why this happens:
- Email is already associated with another account
- Wallet address is linked to a different profile
- Sign out completely
- Sign in with the method you want to keep as primary
- If you have multiple accounts, contact support to merge them
- Avoid creating duplicate accounts with same email
Lost access to wallet - can I recover my account?
Lost access to wallet - can I recover my account?
If you linked Google:
✅ Yes! Sign in with Google, your stories are safe.If wallet-only:
❌ No recovery possible. Wallet private key = your only access.Prevention:
- Always link a Google account as backup
- Store wallet seed phrase securely (never share it)
- Consider hardware wallet for high-value accounts
Session Management
Token Storage
| Method | Storage Location | Expiry | Auto-Refresh |
|---|---|---|---|
| Wallet JWT | localStorage.estory_wallet_token | 30 days | No (re-sign required) |
| Google Session | Supabase session cookie | 1 hour | Yes (rolling refresh) |
Logout Behavior
Signing out clears all authentication tokens and wipes vault encryption keys from memory.
- Supabase session cleared (Google users)
estory_wallet_tokenremoved fromlocalStorage- Vault DEKs cleared via
clearAllKeys()(lib/vault) - User redirected to landing page
- IndexedDB vault data remains encrypted (requires PIN to unlock)
Best Practices
Use Both Methods
Link wallet + Google for maximum flexibility. Sign in with Google for convenience, use wallet for NFT minting.
Secure Your Wallet
Never share your seed phrase. Use hardware wallet (Ledger, Trezor) for accounts holding NFTs or tokens.
Enable 2FA on Google
Add two-factor authentication to your Google account for extra security layer.
Test Signatures First
Practice signing messages on testnet before using mainnet wallet with real funds.
Next Steps
Record Your First Story
Start capturing memories with voice recording and AI transcription.
Set Up Local Vault
Enable client-side encryption for maximum privacy.