Goal: know reliably who accesses NutriSync, make sign-up/sign-in effortless on every surface, and keep the health-data bar (GDPR art. 9) intact. This document is the decision paper for founders; nothing here is built yet except what is marked LIVE.
Supabase Auth with email + password on all four surfaces; sessions persist per device with rotating refresh tokens and the current expiry policy; every data row is protected by RLS keyed to the authenticated user id; admin powers are a separate allowlist (admins) on top of normal accounts. This is sound — the gaps are convenience (typing passwords), recovery (forgotten passwords, as the founders just experienced) and provider choice.
Supabase supports both natively; the app adds two buttons, the web adds two redirects. Two non-negotiables to plan around: Apple's rule — if we offer any third-party login (Google), the App Store requires Sign in with Apple too, so they ship together or not at all; and account linking — same email across providers must resolve to one NutriSync account (Supabase identity linking handles this; we enable it deliberately and test it).
Why it matters for the pilot: the partner recommendation is right — in Indonesia (and broadly on Android) Google Sign-In is the dominant, most reliable path; on iOS, Apple Sign-In removes the password entirely. Both give us a verified email identity from the provider, which strengthens "we know who registered".
Supabase's built-in signInWithOtp: no password to forget, works everywhere email works, and doubles as the recovery path. Password login stays available — OTP is an additional method, and our pilot cohorts can A/B which method women actually prefer (the partner's test matrix: OTP vs Apple vs Google).
Honest framing: biometrics never replace server authentication — the phone proves "same person as last time" locally and unlocks the stored session. The right pattern (industry standard for health apps): refresh token in the device's secure enclave (SecureStore/Keystore), app-lock screen gated by expo-local-authentication, optional toggle in Settings → Sign In & Security ("Unlock with Face ID"), password/OTP always available as fallback, session expiry unchanged. Requires a native rebuild (new module + FaceID entitlement) — lands with the next native version, not OTA.
A custom "tap the push to approve login" flow means building a device registry, push infrastructure, anti-phishing number matching and recovery paths — bank-grade plumbing for marginal gain over 2.2/2.3. The standards-based replacement is passkeys (WebAuthn): same UX promise (biometric, no password, phishing-proof) with platform support. Supabase's passkey support is not yet GA; we put passkeys on the watchlist and adopt them when it lands, instead of hand-rolling push auth.
auth.users + our tables — the proposal adds nothing that touches art. 9 data.| Phase | Contents | Effort | Native rebuild? |
|---|---|---|---|
| A | Google + Apple Sign-In, email OTP, email verification, admin TOTP MFA, access log | 1–2 sessions | Apple Sign-In: yes (entitlement) → bundled with next build |
| B | Biometric app-lock (SecureStore + local auth), Settings toggle | 1 session | yes — same build as A |
| Watchlist | Passkeys when Supabase GA; SMS OTP only if pilot data demands it (cost + Indonesia deliverability review first) | — | — |
One combined native build ships A+B (version bump, TestFlight build 3); everything else is config + JS/OTA.
1A Google + Apple Sign-In together · 2A TOTP MFA mandatory for the 4 admin accounts · 3B biometric app-lock offered right after first login (declinable) · 4B new users see providers/OTP first, password stays as fallback. Implementation = Epic K phases A+B, one native build.
Providers receive only authentication traffic — no health data leaves Supabase. Privacy policy gains: list of identity providers, biometric processing note (on-device only, never transmitted — Face ID templates never reach us), access-log purpose & retention. Apple privacy nutrition labels updated at the same time.