Passkey Authentication
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?
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
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
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
interface PasskeySignUpOptions { /** User's email address (required) */ email: string; /** Display name (optional) */ displayName?: string;}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
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
interface PasskeyLoginOptions { /** Preferred authenticator attachment */ authenticatorAttachment?: 'platform' | 'cross-platform'; /** Whether to use conditional UI (autofill) */ conditionalUI?: boolean;}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({ conditionalUI: true }) .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
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 { id, publicKey, ... }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
interface PasskeyRegisterOptions { /** Preferred authenticator attachment */ authenticatorAttachment?: 'platform' | 'cross-platform';}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
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
- 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