Login Flow (Supabase OAuth + Local Session)
This document is a future-facing operational reference for how login currently works in PATTTTERNS.
Scope
- Authentication model: client-side Supabase OAuth (Google)
- Session storage: browser localStorage
- Callback path:
/auth/callback - No server session runtime (static-export friendly)
Entry Points
- User clicks sign in from UI.
- App builds OAuth URL with Supabase provider config.
- User completes provider consent.
- Supabase redirects browser to
/auth/callbackwith tokens in URL hash. - Callback page persists session and redirects to the original requested path.
Implementation Map
- OAuth URL builder and token/session utilities:
src/lib/auth-client.tsx
- Callback completion page:
src/app/auth/callback/page.tsx
- Auth context consumer/provider:
src/components/AuthSessionProvider.tsxsrc/lib/auth-client.tsx
Detailed Sequence
1) Sign-in trigger
buildSupabaseOAuthUrl(provider, callbackUrl)builds a provider authorize URL.- Redirect target is encoded in
nextquery param on/auth/callback.
2) Provider callback
- Browser lands on
/auth/callbackwith:access_tokenrefresh_tokenexpires_inin URL hash.
3) Session finalization
completeSupabaseOAuthFromUrl(currentUrl)does:- parse hash tokens
- fetch user profile from Supabase
/auth/v1/user - write local session (
patttterns-auth-session) to localStorage - return success + next path
4) Redirect after login
- Callback page redirects to
nextpath on success. - Redirects to
/on failure.
5) Session restore on app load
restoreSupabaseSession()reads local session.- If token still valid, refreshes user profile.
- If expired, attempts refresh token flow.
- If refresh fails, clears local session.
Storage Contract
Local key:
patttterns-auth-session
Stored shape:
accessTokenrefreshTokenexpiresAtuser(normalized user object)
Sign-out
signOutFromSupabase(accessToken)calls Supabase logout endpoint.- localStorage session is cleared.
Required Environment Variables
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
Optional feature flags:
NEXT_PUBLIC_STATIC_LOGIN_MODENEXT_PUBLIC_BOOKMARK_SYNC_BACKEND
Failure Modes
- Missing env vars
- Symptom: sign-in button appears but OAuth URL is null.
- Fix: set Supabase URL + anon key.
- Callback missing tokens
- Symptom: callback page shows failure and sends user home.
- Fix: verify provider and Supabase redirect URL configuration.
- Session silently lost
- Symptom: user appears logged out after reload.
- Fix: inspect refresh flow and ensure refresh token exchange succeeds.
- Wrong return path after login
- Symptom: users always return to home.
- Fix: verify
nextquery param propagation in sign-in trigger.
Operational Notes
- This flow is intentionally browser-centric to stay compatible with static deployment.
- Keep auth logic centralized in
src/lib/auth-client.tsx; avoid duplicate token parsing in components. - For future migration to server sessions, preserve callback compatibility to avoid breaking existing links.