Skip to content

Passkey Authentication

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.

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

Before showing Passkey UI, check if the browser supports WebAuthn:

// Synchronous check
if (auth.passkey.isSupported()) {
// Show Passkey login button
}
// Check if Conditional UI (autofill) is available
const hasConditionalUI = await auth.passkey.isConditionalUIAvailable();

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);
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;
}
  1. SDK sends a registration request to the Authrim server
  2. Server returns WebAuthn creation options (challenge, relying party info)
  3. Browser prompts the user for biometric verification
  4. Browser creates a public key credential
  5. SDK sends the credential back to the server
  6. Server creates the user account, stores the credential, and returns a session

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.

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 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 availability
if (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();

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
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;
}

Common passkey errors:

Error CodeMeaningUser Action
AR003001WebAuthn not supportedShow alternative login methods
AR003002User cancelled the ceremonyAllow retry or offer alternatives
AR003003Credential not foundPrompt user to sign up or use another method
AR003004Authenticator errorRetry or contact support
AR003005Server validation failedRetry 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);
}
}
import { createAuthrim } from '@authrim/web';
const auth = await createAuthrim({
issuer: 'https://auth.example.com',
clientId: 'my-app',
});
// Check support
if (!auth.passkey.isSupported()) {
document.getElementById('passkey-section').style.display = 'none';
}
// Sign in button
document.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 button
document.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');
});