Set Up Supabase Auth in a React Native (Expo) App
By Arslan Shaukat
Authentication is the part most tutorials hand-wave — they show a sign-in form and skip the parts that actually matter: persisting the session across app restarts, reacting to auth changes, and gating screens. Supabase makes the backend trivial; here's how to wire it cleanly into an Expo app.
1. Install
npx expo install @supabase/supabase-js @react-native-async-storage/async-storageAsyncStorage is what lets the session survive an app restart — without it, users get logged out every time they close the app.
2. Create the client
import { createClient } from "@supabase/supabase-js";
import AsyncStorage from "@react-native-async-storage/async-storage";
export const supabase = createClient(
process.env.EXPO_PUBLIC_SUPABASE_URL!,
process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY!,
{
auth: {
storage: AsyncStorage,
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false,
},
}
);detectSessionInUrl: false matters on mobile — that option is for web OAuth redirects and will misbehave in a native app.
3. Sign in and sign up
// sign up
await supabase.auth.signUp({ email, password });
// sign in
const { error } = await supabase.auth.signInWithPassword({ email, password });Always surface error to the user — a silent failure on a login screen is the worst kind.
4. Track the session globally
Wrap your app in a provider that holds the session and updates on every auth change:
const [session, setSession] = useState<Session | null>(null);
useEffect(() => {
supabase.auth.getSession().then(({ data }) => setSession(data.session));
const { data: sub } = supabase.auth.onAuthStateChange((_e, s) =>
setSession(s)
);
return () => sub.subscription.unsubscribe();
}, []);Now any screen can read whether the user is signed in, and the UI reacts instantly to sign-in and sign-out.
5. Protect routes
With Expo Router, redirect based on the session:
if (!session) return <Redirect href="/sign-in" />;Put that in a layout for your authenticated group so every screen inside is guarded in one place.
Gotchas
- Persist with AsyncStorage or sessions vanish on restart.
- Unsubscribe from the auth listener on unmount to avoid leaks.
- Confirm-email flows differ from instant sign-in — decide which you want in the Supabase dashboard early.
That's a complete, production-shaped auth flow. If you'd rather start from a version that already has this wired in — provider, persistent session, and protected routes — my React Native Starter ships with Supabase auth ready to go.
Skip the boilerplate
Production-ready React Native starters and UI kits — buy once, clone, and start on the feature that matters.
Browse the templatesMore