Authentication
WalletSdk.auth exposes WalletAuth — passkey-based authentication with recovery codes. There are no passwords: registration creates a platform passkey (FIDO2 / WebAuthn), and sign-in performs a passkey assertion.
WalletAuth is UI-agnostic. Every operation returns a typed AuthResult; expected failures (not registered, already registered, user cancelled the passkey sheet) are values, not exceptions. Only transport-level errors throw.
The AuthResult type
sealed class AuthResult {}
/// Session established (login, register, full recovery).
/// recoveryCodes is non-empty only after registration.
final class AuthSuccess extends AuthResult {
final AuthSession session;
final List<String> recoveryCodes;
}
/// Username-only recovery succeeded; no session — user signs in next.
final class UsernameRecovered extends AuthResult {
final String username;
final String? userId;
}
/// Expected failure. `cancelled` is true when the user dismissed
/// the platform passkey UI.
final class AuthFailure extends AuthResult {
final AuthErrorCode code;
final String? message;
final bool cancelled;
}
AuthSession carries the bearer token, username, optional userId, and issuedAt.
Register
Creates a new user and a passkey on this device:
switch (result) {
case AuthSuccess(:final session, :final recoveryCodes):
// Display recoveryCodes now — this is the only time they are returned.
showRecoveryCodes(recoveryCodes);
onSignedIn(session);
case AuthFailure(:final code, :final cancelled):
if (cancelled) return; // user dismissed the passkey sheet
if (code == AuthErrorCode.userAlreadyRegistered) {
// Offer login instead.
}
case UsernameRecovered():
break; // not returned by register
}
AuthSuccess.recoveryCodes is populated only on registration. Persisting or re-displaying them is your app's responsibility — the SDK does not store them.
Sign in
Handle the result exactly as above. Relevant failure codes include usernameNotRegistered, authenticationFailed, authVerificationFailed, and userCredentialsNotFound.
Restore a session on cold start
Sessions persist in platform secure storage. Skip the passkey ceremony when a valid session exists:
final session = await sdk.auth.restoreSession();
if (session != null) {
onSignedIn(session); // session.token, session.username
} else {
showAuthScreen();
}
Related helpers:
// Token + username without constructing a session object.
final (:token, :username) = await sdk.auth.readStoredCredentials();
// Just the username (e.g. to prefill the login field).
final username = await sdk.auth.readStoredUsername();
// The registered user id for a username, when known.
Recovery
Two scenarios, selected with RecoveryScenario:
| Scenario | Verifies code | Resets passkey | Creates session | Returns |
|---|---|---|---|---|
userNameOnly | Yes | No | No | UsernameRecovered |
fullRecovery | Yes | Yes | Yes | AuthSuccess |
Username-only — the user forgot which email they registered with:
final result = await sdk.auth.recover(
code: enteredRecoveryCode,
scenario: RecoveryScenario.userNameOnly,
);
if (result case UsernameRecovered(:final username)) {
prefillLoginField(username); // user signs in normally afterward
}
Full recovery — the user lost their passkey (new device, cleared credentials). The code is verified, a new passkey is registered, and a session is established:
final result = await sdk.auth.recover(
code: enteredRecoveryCode,
scenario: RecoveryScenario.fullRecovery,
);
if (result case AuthSuccess(:final session)) {
onSignedIn(session);
}
Generate fresh codes for a signed-in user (invalidates prior codes):
final codes = await sdk.auth.generateRecoveryCodes();
showRecoveryCodes(codes);
Logout
// Clear the auth token but keep the stored username (typical sign-out).
await sdk.auth.logout();
// Clear everything, including the stored username.
await sdk.auth.logout(authTokenOnly: false);
clearStoredSession clears local session state without a backend call:
await sdk.auth.clearStoredSession(); // authTokenOnly: false by default
Error codes
AuthFailure.code is an AuthErrorCode. The SDK never carries localized strings — map codes to your own copy:
| Group | Codes |
|---|---|
| Registration | registrationFailed, registrationAborted, registrationVerificationFailed, userAlreadyRegistered |
| Login | authenticationFailed, authenticationAborted, authVerificationFailed, usernameNotRegistered, userCredentialsNotFound |
| Recovery | recoveryFailed, recoveryAborted, recoveryCodeVerificationFailed, passkeyResetFailed, recoveryCodesGenerationFailed |
| Logout | logoutFailed |
| Generic | unexpected |
Observing auth events
Provide an AuthObserver in WalletSdkOptions to receive lifecycle callbacks for analytics or crash-reporting context — see Configuration.