Authentication
Sign-up, sign-in, two-factor, one-time codes, OAuth, anonymous users and admin sign-in with the Dart SDK.
Every flow of an auth collection is on vb.auth.collection(name); admin
sign-in is on vb.auth.admin. A sign-in stores the session in
vb.authStore, and every request after it carries the token.
final users = vb.auth.collection('users');Sign-in results
Section titled “Sign-in results”Sign-ins that can stop halfway return a sealed AuthResult, so a switch
covers every case:
final result = await users.login(email, password);switch (result) { case SignedIn(:final record): print('signed in as ${record['email']}'); case MfaRequired(:final mfaToken): // two-factor is on: nothing is stored yet await users.loginMfa(mfaToken, code: codeFromAuthenticator); case MergeRequired(): // only from OAuth; see below}SignedIn carries token and record. Flows that can’t stop halfway
(anonymous, promote, loginMfa) return SignedIn directly.
The session
Section titled “The session”vb.auth.isSignedIn; // a token that hasn't expiredvb.authStore.record; // the signed-in user (or admin) as a mapvb.authStore.onChange; // Stream<StoredAuth?>: sign-in, refresh, sign-outawait vb.auth.me(); // the user, fresh from the serverawait vb.auth.refresh(); // a new token now; storedawait vb.auth.logout(); // revokes the token on the server and clears the storeRefreshing is automatic: 60 seconds before the token expires, and once after
a 401. You rarely call refresh() yourself.
Email and password
Section titled “Email and password” data: {'name': 'Ann'}); // doesn't sign inSign-up must be open on the collection (its create rule).
Verification, password reset, email change
Section titled “Verification, password reset, email change”await users.requestVerification(); // emails the signed-in userawait users.confirmVerification(tokenFromLink);
await users.confirmPasswordReset(tokenFromLink, 'new-password');
await users.confirmEmailChange(tokenFromLink, 'current-password'); // signs out
await users.acceptInvite(tokenFromInvite, 'chosen-password');One-time codes
Section titled “One-time codes”// or, from the emailed link:await users.authWithOtp(token: tokenFromLink);Two-factor (authenticator apps)
Section titled “Two-factor (authenticator apps)”final setup = await users.setupTotp();// show setup.otpauthUrl as a QR code (or setup.secret to type in)final recoveryCodes = await users.confirmTotp(codeFromApp); // show these once
await users.recoveryCodeStatus(); // (total: 10, remaining: 9)await users.regenerateRecoveryCodes(codeFromApp);await users.disableTotp(codeFromApp);A sign-in then returns MfaRequired; finish it with
loginMfa(mfaToken, code: ...) or loginMfa(mfaToken, recoveryCode: ...).
Anonymous users
Section titled “Anonymous users”await users.anonymous(); // a new guest accountAnonymous sign-in is off by default (auth.anonymous.enabled).
In a Flutter app, use signInWithOAuth2, which handles the browser: see
Flutter. The steps underneath, for other
set-ups:
final providers = await users.oauth2Providers();final start = await users.oauth2Authorize('github', redirectUri, usePkce: true);// send the user to start.authorizeUrl; the provider redirects to redirectUrifinal result = await users.oauth2ExchangeRedirect('github', redirectUri, redirectedTo);The client remembers the state secret from oauth2Authorize; if another
client instance handles the redirect, pass stateSecret: yourself.
Native sheets
Section titled “Native sheets”An ID token from the platform’s sign-in sheet (Sign in with Apple, Google sign-in) signs in without a browser:
final nonce = await users.idTokenNonce('apple'); // required for Apple// ... the sheet, given the nonce, returns an ID token ...await users.signInWithIdToken('apple', idToken, nonce: nonce, name: name);See Flutter for both providers end to end.
When the provider’s email matches an existing account, the result is
MergeRequired. Linking needs the account’s password, when it has one:
await users.oauth2MergeConfirm(merge.mergeToken, password: password);await users.oauth2Unlink('github');Admins
Section titled “Admins”final status = await vb.auth.admin.setupStatus(); // (hasAdmin: ..., keyRequired: ...)
// A session for a user, not stored here: use the token in another client.final session = await vb.auth.admin.impersonate('users', userId);