Skip to main content
Providers are enabled in your own Supabase dashboard exactly as they are for a web app — Web → Authentication covers that, and all of it applies here. This page is the part that is different on a phone. Three things change:
Native OAuth redirect

Native OAuth uses a scheme redirect

There is no page to redirect to. iOS opens ASWebAuthenticationSession and Android opens a Custom Tab, the user signs in, and the system hands control back to your app through a custom URL scheme — the same myapp:// scheme used for deep links. Neither expo-auth-session nor expo-web-browser ships in the starter — ask the agent for social sign-in and it installs both. The flow it writes:
Three details do the work:
  • skipBrowserRedirect: true. Without it signInWithOAuth tries to navigate a browser that doesn’t exist here. You want the URL, not the navigation.
  • openAuthSessionAsync(url, redirectTo). The second argument is what tells the system sheet which URL means “done” — it must be the same string you sent to Supabase.
  • setSession. Nothing detects the callback URL for you on native. Until you call setSession, the user is not signed in and nothing is persisted.
If your Supabase client is configured with flowType: "pkce", the callback carries ?code= instead of a token fragment. Swap the last two steps for supabase.auth.exchangeCodeForSession(code) — the rest is identical.

Allowlist the exact value

In your Supabase dashboard → Authentication → URL Configuration → Redirect URLs, add the literal scheme URL:
Not a wildcard, not an https:// URL. It has to match what makeRedirectUri produced, character for character.

The dev-vs-prod trap

makeRedirectUri returns a different value depending on how the app is running, and this is what breaks in production after working all through development: Allowlist both. Only allowlisting the exp:// URL you saw during development means every store build fails sign-in with a dismissed sheet and no error. Two more consequences, both Vibely-specific:
  • Set your scheme before you build. The scheme in app.json comes from Settings → Mobile app → Deep link scheme. Leave it at the template placeholder and the production build is refused with a message telling you to set it — but worse, changing it after you’ve allowlisted a redirect silently invalidates that allowlist entry. Pick the scheme first, allowlist it, then build.
  • The old auth proxy is gone. Guides that tell you to pass useProxy: true or to allowlist https://auth.expo.io/@you/your-app are pre-SDK-48 and no longer work. Use the scheme.
Native OAuth does not work in the web preview either — the web preview has no URL scheme to return to. Test sign-in in Expo Go or on a build.

Sign in with Apple

Use expo-apple-authentication, not the web flow above. It presents the native Apple sheet, which is what App Store reviewers expect to see, and it returns an identity token you hand straight to Supabase:
Notes that cost people a review cycle:
  • iOS only. AppleAuthentication.isAvailableAsync() is false on Android and in the web preview. Render the button conditionally.
  • Name and email arrive once. Apple returns fullName and email only on the user’s first authorization. Persist them then; a second sign-in returns nulls.
  • Enable the Apple provider in Supabase and add your bundle ID as an authorized client — see auth-apple.

Guideline 4.8

If your app offers a third-party or social login — Google, Facebook, X — App Store Review Guideline 4.8 requires you to also offer an equivalent login option that:
  • limits data collection to the user’s name and email address;
  • lets the user keep their email address private from your app; and
  • does not collect interactions with your app for advertising without consent.
Sign in with Apple satisfies all three and is the shortest path. Plain email/password does not — it cannot mask the address, so it fails the second clause. The rule only bites if you offer a social login at all: an app with nothing but email/password has no 4.8 obligation. See Ship.

Sessions

The starter’s Supabase client already points auth.storage at a Keychain / Android Keystore–backed store (src/integrations/supabase/secure-storage.ts, chunked past the platform’s 2048-byte item limit). Sessions survive a relaunch and refresh themselves. Leave that file alone, and never move identity into AsyncStorage — it is unencrypted. See Native → Secure storage. For “Unlock with Face ID”, gate a session that is already on the device — don’t use biometrics as the primary credential. Native → Biometrics has the pattern.

Checklist before you ship

  1. Both redirect values allowlisted in Supabase — the exp:// dev URL and myapp://auth-callback.
  2. Deep link scheme set in Settings → Mobile app, and it matches the allowlisted URL.
  3. Sign-in tested on a real build, not just Expo Go.
  4. Sign in with Apple present if any other social login is.
  5. A way to try the app, or at least see what it does, without an account — reviewers reject blank login walls.