Demo, all content is generated
Question

Supabase Google login in Expo redirects to localhost:3000 and the app never gets the session

Solved · 691 views · asked by nightowl_nina · edited

Web version of my app uses Google login via Supabase and it's fine. In the Expo app I call signInWithOAuth, the browser opens, I pick my Google account, and then it tries to load http://localhost:3000/#access_token=... and just shows "Safari can't open the page".

I can literally see the access token in the URL so the login worked?

What I’ve tried

Added my scheme "nina-app://" to the Supabase redirect URLs. Cursor added expo-auth-session and a bunch of code, same result.

Comment

3 answers

Marked as helpful by the asker
jb_supa · edited

The login worked, but Supabase fell back to your Site URL (localhost:3000) because you didn't pass a redirectTo it recognises. And even with the right URL, on native you have to catch the redirect yourself and set the session:

import * as WebBrowser from "expo-web-browser";
import { makeRedirectUri } from "expo-auth-session";

const redirectTo = makeRedirectUri(); // nina-app:// in a build, exp://... in Expo Go

const { data } = await supabase.auth.signInWithOAuth({
  provider: "google",
  options: { redirectTo, skipBrowserRedirect: true },
});

const res = await WebBrowser.openAuthSessionAsync(data!.url, redirectTo);
if (res.type === "success") {
  const params = new URLSearchParams(res.url.split("#")[1]);
  await supabase.auth.setSession({
    access_token: params.get("access_token")!,
    refresh_token: params.get("refresh_token")!,
  });
}

Then in Supabase → Authentication → URL Configuration, add the exact value makeRedirectUri() returns (log it) to Redirect URLs. In Expo Go that's an exp://192.168... URL which changes with your network, so test in a development build.

Comment
skipBrowserRedirect + openAuthSessionAsync was the missing piece. works in the dev build now nightowl_nina · edited
The exp:// changing with network thing cost me an evening last week. Wish I had seen this. tuan_ng · edited
amir_h · edited

If you're on a newer supabase-js, consider PKCE flow (flowType: "pkce" in the client options) and exchangeCodeForSession. You get a ?code= back instead of tokens in the fragment, which is cleaner on mobile.

Comment
pixelpaulo · edited

Also check your Supabase client setup in the Expo app. If you copied it from a web project, set storage: AsyncStorage, autoRefreshToken: true, persistSession: true and detectSessionInUrl: false. Without the last one I had weird double-login behaviour.

Comment
detectSessionInUrl false was already there luckily nightowl_nina · edited