Passkey Authentication
Overview
Section titled “Overview”Passkeys provide passwordless authentication using biometrics (fingerprint, face recognition) or security keys. The SDK’s auth.passkey namespace wraps the WebAuthn API, handling credential creation, assertion, and server-side verification.
What Are Passkeys?
Section titled “What Are Passkeys?”Passkeys are FIDO2/WebAuthn credentials stored on the user’s device or in a platform authenticator (iCloud Keychain, Google Password Manager, Windows Hello). They are:
- Phishing-resistant — Credentials are bound to the origin (domain)
- No passwords — Users authenticate with biometrics or a PIN
- Synced across devices — Platform authenticators sync passkeys via cloud
Checking Support
Section titled “Checking Support”Before showing Passkey UI, check if the browser supports WebAuthn:
// Synchronous checkif (auth.passkey.isSupported()) { // Show Passkey login button}
// Check if Conditional UI (autofill) is availableconst hasConditionalUI = await auth.passkey.isConditionalUIAvailable();Sign Up
Section titled “Sign Up”Create a new account with a Passkey. This creates the user and registers a WebAuthn credential in a single step:
const { data, error } = await auth.passkey.signUp({});
if (error) { console.error('Sign up failed:', error.message); return;}
console.log('Account created:', data.user);console.log('Session:', data.session);Sign Up Options
Section titled “Sign Up Options”interface PasskeySignUpOptions { /** User's email address (required) */ email: string; /** Display name (optional) */ displayName?: string; /** Preferred authenticator type */ authenticatorType?: 'platform' | 'cross-platform' | 'any'; /** Resident key requirement */ residentKey?: 'required' | 'preferred' | 'discouraged'; /** User verification requirement */ userVerification?: 'required' | 'preferred' | 'discouraged'; /** Abort signal for cancellation */ signal?: AbortSignal;}What Happens Internally
Section titled “What Happens Internally”- SDK sends a registration request to the Authrim server
- Server returns WebAuthn creation options (challenge, relying party info)
- Browser prompts the user for biometric verification
- Browser creates a public key credential
- SDK sends the credential back to the server
- Server creates the user account, stores the credential, and returns a session
Sign In
Section titled “Sign In”Authenticate an existing user with their Passkey:
const { data, error } = await auth.passkey.login();
if (error) { console.error('Login failed:', error.message); return;}
console.log('Welcome back:', data.user);No email or username is needed — the browser presents available passkeys for the current origin.
Login Options
Section titled “Login Options”interface PasskeyLoginOptions { /** Whether to use conditional UI (autofill) */ conditional?: boolean; /** Mediation preference */ mediation?: 'conditional' | 'optional' | 'required' | 'silent'; /** Abort signal for cancellation */ signal?: AbortSignal;}Conditional UI (Autofill)
Section titled “Conditional UI (Autofill)”Conditional UI integrates Passkey selection into the browser’s autofill menu. Instead of a dedicated “Sign in with Passkey” button, users see their passkeys in the same autofill dropdown as saved passwords:
// Check availabilityif (await auth.passkey.isConditionalUIAvailable()) { // Start conditional UI (non-blocking) auth.passkey.login({ conditional: true, mediation: 'conditional' }) .then(({ data, error }) => { if (data) { console.log('Signed in via autofill:', data.user); } });}To cancel a pending conditional UI request (e.g., when navigating away):
auth.passkey.cancelConditionalUI();Register Additional Passkey
Section titled “Register Additional Passkey”Add a new passkey to an existing account. The user must already be authenticated:
const { data, error } = await auth.passkey.register();
if (error) { console.error('Registration failed:', error.message); return;}
console.log('New passkey registered:', data);// data: PasskeyCredential { credentialId, publicKey, authenticatorType, ... }This is useful for:
- Adding a security key as a backup
- Registering a passkey on a new device
- Settings/profile page “Add Passkey” feature
Register Options
Section titled “Register Options”interface PasskeyRegisterOptions { /** Passkey display name */ displayName?: string; /** Preferred authenticator type */ authenticatorType?: 'platform' | 'cross-platform' | 'any'; /** Resident key requirement */ residentKey?: 'required' | 'preferred' | 'discouraged'; /** User verification requirement */ userVerification?: 'required' | 'preferred' | 'discouraged'; /** Abort signal for cancellation */ signal?: AbortSignal;}Error Handling
Section titled “Error Handling”Common passkey errors:
| Error Code | Meaning | User Action |
|---|---|---|
AR003001 | WebAuthn not supported | Show alternative login methods |
AR003002 | User cancelled the ceremony | Allow retry or offer alternatives |
AR003003 | Credential not found | Prompt user to sign up or use another method |
AR003004 | Authenticator error | Retry or contact support |
AR003005 | Server validation failed | Retry the operation |
const { data, error } = await auth.passkey.login();
if (error) { switch (error.code) { case 'AR003002': // User cancelled — do nothing or show subtle message break; case 'AR003003': // No credential — suggest sign up showMessage('No passkey found. Would you like to sign up?'); break; default: showMessage(error.message); }}Complete Example
Section titled “Complete Example”import { createAuthrim } from '@authrim/web';
const auth = await createAuthrim({ issuer: 'https://auth.example.com', clientId: 'my-app',});
// Check supportif (!auth.passkey.isSupported()) { document.getElementById('passkey-section').style.display = 'none';}
// Sign in buttondocument.getElementById('passkey-login').addEventListener('click', async () => { const { data, error } = await auth.passkey.login(); if (error) { alert(error.message); return; } window.location.href = '/dashboard';});
// Sign up buttondocument.getElementById('passkey-signup').addEventListener('click', async () => { const email = document.getElementById('email-input').value; const { data, error } = await auth.passkey.signUp({ email }); if (error) { alert(error.message); return; } window.location.href = '/dashboard';});
// Add passkey button (profile page, user already authenticated)document.getElementById('add-passkey').addEventListener('click', async () => { const { data, error } = await auth.passkey.register(); if (error) { alert(error.message); return; } alert('Passkey added successfully');});Next Steps
Section titled “Next Steps”- Email Code Authentication — Alternative passwordless method
- Social Login — Third-party identity providers
- Session Management — Working with sessions after login
- Error Handling — Comprehensive error handling guide