Skip to main content
Vantage uses Supabase Auth with two sign-in methods: email/password and Google OAuth via PKCE. The backend validates every API request against Supabase’s JWKS endpoint, with a 300-second token cache to reduce round-trips.

Flutter auth flow

Email/password

Google OAuth (PKCE)

The redirectTo URI is registered in AndroidManifest.xml as a deep link intent filter. Supabase handles the PKCE code exchange internally — no server-side callback route needed. The redirect URI must be added to Supabase Auth → Providers → Google → Redirect URLs: com.vantagewealth.app://callback

Seed data remap

New Supabase accounts are created with a trigger that auto-populates demo data linked to a placeholder UUID (00000000-0000-0000-0000-000000000001). On first sign-in, Vantage calls remap_seed_data() to re-link everything to the real user’s UUID:
The remap_seed_data PostgreSQL function updates every foreign key and array member across all tables in a single transaction.

Backend JWT validation

Every FastAPI endpoint that accesses user data uses the get_current_user dependency:
The JWT cache key is the full token string. TTL is 300 seconds — matching Supabase’s JWT expiry behaviour. After expiry, the next request re-validates against Supabase. Security guarantee: Because RLS is enforced on every Supabase query, even if a token were somehow spoofed, all queries would return empty results for any user_id that doesn’t match auth.uid().

Biometric lock

The 30-second timeout prevents the lock screen from appearing when the user briefly switches apps. Lock state is stored in-memory only — it resets on cold start. The /lock screen uses local_auth to prompt Face ID / fingerprint. On success it sets isUnlocked = true and pops back to the previous route.

Debug mode

This is stripped from release builds by the Dart compiler (kDebugMode = false in release mode).

Auth state management

The Supabase Flutter SDK persists the session in secure storage (flutter_secure_storage). On cold start, supabase.auth.currentSession is non-null if a valid session exists — no network call needed. The go_router redirect fires on every navigation attempt:
Session changes (sign-in, sign-out, token refresh) trigger a notifyListeners() on the GoRouter’s refresh listenable, which re-evaluates the redirect.