Authentication Structure
Route Map
Frontend routes
app/(shared)/auth.tsx->/authapp/(shared)/auth/callback.tsx->/auth/callbackapp/auth/index.tsx->/auth/trailing-slash compatibilityapp/auth/callback/index.tsx->/auth/callback/trailing-slash compatibility
API auth routes
app/api/auth/oauth/login+api.ts->/api/auth/oauth/loginapp/api/auth/oauth/callback+api.ts->/api/auth/oauth/callbackapp/api/auth/oauth/google+api.ts-> legacy compatibility callback for older Google links
Current Main Google Flow (updated 2026-07-08)
Main Google sign-in starts in apps/mobile-app/hooks/useAuth.ts through signInWithOAuth('google').
Web and native now try Better Auth first, for every tenant (not just BSL events) — see AUTH_FLOW.md for the full sequence:
- Web calls Better Auth's
signIn.social({ provider: 'google' }), which redirects to Google withredirect_uri=<apiBase>/api/auth/callback/google. - Better Auth's own server exchanges the code, sets a session cookie, and redirects back to
/auth/callback. app/(shared)/auth/callback.tsxchecks for a live Better Auth session first (via alocalStoragemarker set before the redirect) before falling back to the tenant's resolved provider.- Only if Better Auth's own request errors does the code fall back to
supabase.auth.signInWithOAuth({ provider: 'google' }), which then follows the oldcreateSessionFromUrl()PKCE-exchange path described below. - Native uses
@react-native-google-signin/google-signinfor the account picker, exchanges the Google ID token with Better Auth first, then falls back tosupabase.auth.signInWithIdToken()only if Better Auth fails.
Directus Fallback Flow (not reachable from the Google button)
This bridge still exists in the tree but nothing calls it for provider=google anymore — see AUTH_FLOW.md § Do we still need Directus?. Left here for reference in case a non-Google provider is ever wired up, or Google sign-in ever falls all the way through both Better Auth and Supabase:
The API:
- Validates the
returnTopath. - Stores return-target, frontend-origin, and optional native callback cookies.
- Redirects to Directus with
redirect=https://api.hashpass.tech/api/auth/oauth/callback&mode=session. - Lets Directus complete the Google handshake and return to
/api/auth/oauth/callback. - Resolves the Directus response and returns either:
- a web fragment redirect with the Directus tokens, or
- a native
hashpass://auth/callback?...redirect for the mobile app.
The frontend or native app then reads the returned tokens and hydrates the active session.
Why /auth/callback Still Exists
The frontend callback route is still useful because it:
- normalizes token delivery on the client
- preserves compatibility with older local flows
- exchanges Supabase PKCE and token-hash callbacks
- handles trailing-slash redirects from static hosting
- returns native app redirects when
native_callbackis present
Multi-Origin Support
The auth flow accepts multiple trusted frontend origins through environment configuration and runtime checks. The production path is currently centered on:
https://hashpass.techhttps://dev.hashpass.techhttps://api.hashpass.techhttps://sso.hashpass.cohttp://localhost:8081for local web development
For the latest operational flow and troubleshooting notes, see AUTH_FLOW.md.