From Supabase Auth
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.auth | Authyra.instance (or an injected AuthyraClient) |
User | AuthUser |
auth.onAuthStateChange | Authyra.instance.authStateChanges |
signInWithPassword | signIn('email', params: CredentialsSignInParams(...)) |
signInWithOAuth | signIn('google') via GoogleProvider, or your own OAuth2Provider |
auth.currentSession | Authyra.instance.currentState (sync) or await Authyra.instance.getSession() |
session.accessToken | Authyra.instance.getAccessToken() |
signOut() | Authyra.instance.signOut() |
| Multiple client instances for multi-account | Authyra.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');
});