Migration

From Supabase Auth

Map Supabase Auth concepts and calls to Authyra.

Same spirit as the Firebase page: this isn't "Supabase is worse." If Supabase works as your backend, keep it, wrap its client inside an AuthProvider. This page is for consolidating Supabase auth (or a second provider alongside it) behind one consistent app-side API.


Concept mapping

Supabase (GoTrueClient)Authyra
Supabase.instance.client.authAuthyra.instance (or an injected AuthyraClient)
UserAuthUser
auth.onAuthStateChangeAuthyra.instance.authStateChanges
signInWithPasswordsignIn('email', params: CredentialsSignInParams(...))
signInWithOAuthsignIn('google') via GoogleProvider, or your own OAuth2Provider
auth.currentSessionAuthyra.instance.currentState (sync) or await Authyra.instance.getSession()
session.accessTokenAuthyra.instance.getAccessToken()
signOut()Authyra.instance.signOut()
Multiple client instances for multi-accountAuthyra.instance.accounts, one client, switchTo/signOut(userId)/signOutAll

What moves, what doesn't

Session storage. Supabase's client persists its own session (AsyncStorage/local storage under the hood). Authyra needs an explicit AuthStorage, SecureAuthStorage for Flutter apps.

Token refresh. Supabase's client auto-refreshes internally. Authyra's equivalent is AuthConfig(autoRefresh: true) (the default) plus your provider setting supportsRefresh: true and implementing refreshToken.

Row Level Security. If your Postgres RLS policies depend on the Supabase JWT's claims, keep issuing Supabase JWTs, just wrap the sign-in call in your AuthProvider and forward session.accessToken as the Supabase JWT when calling the Supabase REST/Postgrest APIs. Authyra doesn't replace that token, it just becomes the thing that stores and refreshes it for you app-side.


Example: email/password backed by Supabase

CredentialsProvider.withTokens(
  id: 'email',
  authorize: (creds) async {
    try {
      final res = await Supabase.instance.client.auth.signInWithPassword(
        email: creds?.email ?? '',
        password: creds?.password ?? '',
      );
      final session = res.session;
      if (session == null) return null;
      return AuthSignInResult(
        user: AuthUser(id: res.user!.id, email: res.user!.email),
        accessToken: session.accessToken,
        refreshToken: session.refreshToken,
        expiresAt: DateTime.fromMillisecondsSinceEpoch(session.expiresAt! * 1000),
      );
    } on AuthException {
      return null; // wrong credentials
    }
  },
)

Example: reactive state

// Supabase
Supabase.instance.client.auth.onAuthStateChange.listen((data) {
  final session = data.session;
  // update your own state holder
});
// Authyra
Authyra.instance.authStateChanges.listen((state) {
  if (state.isAuthenticated) router.go('/dashboard');
});

See also

Copyright © 2026