Sigma Stack
2 min read

Set Up Supabase Auth in a React Native (Expo) App

By Arslan Shaukat

React NativeExpoSupabaseAuth

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-storage

AsyncStorage 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 templates

More

Keep reading