@passkeykit/client
v2.0.0
Published
Client-side WebAuthn passkey helpers for browser-based registration and authentication
Maintainers
Readme
@passkeykit/client
Browser-side WebAuthn passkey authentication. Handles the registration and authentication ceremonies with zero configuration — just point it at your server.
Works with @passkeykit/server or any WebAuthn server that follows the standard challenge-response pattern.
Install
npm install @passkeykit/clientQuick Start
import { PasskeyClient, isWebAuthnAvailable } from '@passkeykit/client';
const client = new PasskeyClient({
serverUrl: '/api/auth/passkey',
});
// Check browser support
if (isWebAuthnAvailable()) {
// Register a new passkey
const reg = await client.register('user-123', 'My MacBook');
console.log('Registered:', reg.credentialId);
// Authenticate with a passkey
const auth = await client.authenticate();
console.log('Authenticated as:', auth.userId);
}API
new PasskeyClient(config)
| Option | Type | Description |
|--------|------|-------------|
| serverUrl | string | Required. Base URL of the passkey API (e.g. /api/auth/passkey) |
| fetch | typeof fetch | Custom fetch function (e.g. to add auth headers). Defaults to globalThis.fetch |
| headers | Record<string, string> | Extra headers included in every request |
| extraBody | Record<string, unknown> | Extra fields merged into every request body. Useful for multi-app servers that need rpId/rpName per request |
client.register(userId, credentialName?, opts?)
Registers a new passkey for a user.
- Fetches registration options from the server
- Triggers the browser's WebAuthn prompt (TouchID / FaceID / Windows Hello / security key)
- Sends the attestation back for server-side verification
const result = await client.register('user-123', 'My Phone', {
authenticatorAttachment: 'platform', // 'platform' | 'cross-platform'
residentKey: 'preferred', // 'required' | 'preferred' | 'discouraged'
userVerification: 'preferred', // 'required' | 'preferred' | 'discouraged'
});
// → { verified: true, credentialId: '...', credentialName: 'My Phone' }client.authenticate(userId?, opts?)
Authenticates with a passkey.
- Without
userId: Discoverable credential flow — the browser picks the passkey - With
userId: Server hints which credentials to use
const result = await client.authenticate();
// → { verified: true, userId: 'user-123', credentialId: '...' }isWebAuthnAvailable()
Returns true if the browser supports WebAuthn (PublicKeyCredential + navigator.credentials).
import { isWebAuthnAvailable } from '@passkeykit/client';
if (!isWebAuthnAvailable()) {
console.log('Passkeys not supported in this browser');
}isPlatformAuthenticatorAvailable()
Async check for platform authenticator support (TouchID, FaceID, Windows Hello).
import { isPlatformAuthenticatorAvailable } from '@passkeykit/client';
if (await isPlatformAuthenticatorAvailable()) {
// Show "Add Passkey" button
}Multi-App Server
When multiple apps share one passkey server, use extraBody to specify the relying party:
const client = new PasskeyClient({
serverUrl: 'https://auth.example.com/api/passkey',
extraBody: {
rpId: 'myapp.example.com',
rpName: 'My App',
},
});Stateless Mode
When used with @passkeykit/server in stateless mode, the client automatically handles challengeToken round-tripping — no extra config needed. The token is returned by the server in the options response and sent back during verification.
Error Handling
All errors thrown by the client are typed PasskeyError with machine-readable error codes:
import { PasskeyClient, PasskeyError } from '@passkeykit/client';
try {
await client.authenticate();
} catch (err) {
if (err instanceof PasskeyError) {
if (err.isCancelled) {
// User closed the WebAuthn prompt — not a real error
return;
}
switch (err.code) {
case 'NETWORK_ERROR': console.log('Check your connection'); break;
case 'SERVER_ERROR': console.log(`Server: ${err.message} (${err.statusCode})`); break;
case 'NOT_SUPPORTED': console.log('WebAuthn not available'); break;
default: console.log('Unknown error:', err.message);
}
}
}Error codes:
| Code | Meaning |
|------|---------|
| USER_CANCELLED | User closed the WebAuthn prompt |
| SERVER_ERROR | HTTP error from the server (includes statusCode) |
| NETWORK_ERROR | Fetch failed (offline, CORS, etc.) |
| NOT_SUPPORTED | WebAuthn not supported or blocked by security policy |
| INVALID_RESPONSE | Server returned unexpected data |
| UNKNOWN | Unrecognized error |
Server Pairing
This package is designed to work with @passkeykit/server, but it's compatible with any server that exposes:
POST /register/options→ returns WebAuthn registration optionsPOST /register/verify→ verifies the attestation responsePOST /authenticate/options→ returns WebAuthn authentication optionsPOST /authenticate/verify→ verifies the assertion response
License
MIT — GitHub
