Supabase Auth handles user registration, login, and session management out of the box. This guide covers setting it up in Flutter with email/password, native Google sign-in, and native Apple sign-in.

For the full reference, see the Supabase Flutter Auth docs.

Setup

Add the Supabase Flutter package to your pubspec.yaml:

yaml
dependencies:
  supabase_flutter: ^2.0.0

Initialize Supabase before your app runs. You can find your project URL and anon key in the Supabase dashboard under Settings → API.

dart
import 'package:supabase_flutter/supabase_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Supabase.initialize(
    url: 'https://your-project.supabase.co',
    anonKey: 'your-anon-key',
  );
  runApp(MyApp());
}

// Access the client anywhere in your app
final supabase = Supabase.instance.client;

Email & Password

Sign Up

Creates a new account. Supabase sends a confirmation email by default. You can disable this in the dashboard under Auth → Settings.

dart
final response = await supabase.auth.signUp(
  email: 'user@example.com',
  password: 'password123',
);
final user = response.user;

Sign In

Logs in an existing user and returns a session with access and refresh tokens. The SDK stores these locally and refreshes them automatically.

dart
final response = await supabase.auth.signInWithPassword(
  email: 'user@example.com',
  password: 'password123',
);
final session = response.session;
final user = response.user;

Sign Out

Clears the local session and invalidates the refresh token.

dart
await supabase.auth.signOut();

Google Sign In

Native Google sign-in gives the best user experience (the system account picker instead of a web view). The flow: your app gets an ID token from Google, then sends it to Supabase to create or log in the user.

You need to set up OAuth credentials in the Google Cloud Console and enable Google as an auth provider in the Supabase dashboard under Auth → Providers. Then add the google_sign_in package.

dart
import 'package:google_sign_in/google_sign_in.dart';

Future<void> signInWithGoogle() async {
  // Show the native Google account picker
  final googleSignIn = GoogleSignIn(
    serverClientId: 'your-web-client-id.apps.googleusercontent.com',
  );
  final googleUser = await googleSignIn.signIn();
  if (googleUser == null) return; // user cancelled

  // Get the ID token from Google
  final googleAuth = await googleUser.authentication;
  final idToken = googleAuth.idToken;
  if (idToken == null) throw 'No ID token';

  // Send the token to Supabase to create/login the user
  await supabase.auth.signInWithIdToken(
    provider: OAuthProvider.google,
    idToken: idToken,
  );
}

Apple Sign In

Works the same way as Google: get an ID token from Apple, send it to Supabase. You need to enable Sign in with Apple in your Xcode project under Signing & Capabilities, and enable Apple as a provider in the Supabase dashboard. Add the sign_in_with_apple package.

dart
import 'package:sign_in_with_apple/sign_in_with_apple.dart';

Future<void> signInWithApple() async {
  // Show the native Apple sign-in sheet
  final credential = await SignInWithApple.getAppleIDCredential(
    scopes: [
      AppleIDAuthorizationScopes.email,
      AppleIDAuthorizationScopes.fullName,
    ],
  );

  // Send the token to Supabase
  await supabase.auth.signInWithIdToken(
    provider: OAuthProvider.apple,
    idToken: credential.identityToken!,
  );
}

Sessions

Supabase handles sessions automatically. The SDK stores the session on the device, refreshes tokens in the background when they expire, and restores the session when the app restarts. You rarely need to manage this yourself.

dart
// Get the current session (null if not logged in)
final session = supabase.auth.currentSession;

// Get the current user (null if not logged in)
final user = supabase.auth.currentUser;

// Quick check
final isLoggedIn = supabase.auth.currentSession != null;

Auth State Changes

Listen to auth events to react when the user signs in, signs out, or the session refreshes. This is where you handle navigation after login or redirect to a login screen after sign out.

dart
supabase.auth.onAuthStateChange.listen((data) {
  final event = data.event;

  switch (event) {
    case AuthChangeEvent.signedIn:
      // User just logged in — navigate to home
      break;
    case AuthChangeEvent.signedOut:
      // User logged out — navigate to login
      break;
    case AuthChangeEvent.tokenRefreshed:
      // Token was refreshed in the background, no action needed
      break;
    default:
      break;
  }
});

A common pattern: listen in your root widget's initStateand redirect based on the event. Or combine with go_router's redirect to guard routes automatically.