0
# SimpleWebAuthn
1
2
SimpleWebAuthn is a comprehensive TypeScript library providing both client-side and server-side WebAuthn functionality for implementing passwordless authentication with passkeys and other WebAuthn-compatible authenticators. It consists of two complementary packages that work together to provide a complete WebAuthn implementation.
3
4
## Package Information
5
6
- **Package Name**: @simplewebauthn/browser and @simplewebauthn/server
7
- **Package Type**: npm (also available on JSR for Deno)
8
- **Language**: TypeScript
9
- **Installation**:
10
- Browser: `npm install @simplewebauthn/browser` or `deno add jsr:@simplewebauthn/browser`
11
- Server: `npm install @simplewebauthn/server` or `deno add jsr:@simplewebauthn/server`
12
13
## Core Imports
14
15
**Browser Package:**
16
17
```typescript
18
import {
19
startRegistration,
20
startAuthentication,
21
browserSupportsWebAuthn,
22
platformAuthenticatorIsAvailable,
23
browserSupportsWebAuthnAutofill,
24
type RegistrationResponseJSON,
25
type AuthenticationResponseJSON,
26
} from "@simplewebauthn/browser";
27
```
28
29
**Server Package:**
30
31
```typescript
32
import {
33
generateRegistrationOptions,
34
verifyRegistrationResponse,
35
generateAuthenticationOptions,
36
verifyAuthenticationResponse,
37
MetadataService,
38
SettingsService,
39
} from "@simplewebauthn/server";
40
41
// Server helpers for advanced use cases
42
import {
43
generateChallenge,
44
generateUserID,
45
convertAAGUIDToString,
46
decodeAttestationObject,
47
parseAuthenticatorData,
48
isoBase64URL,
49
isoUint8Array,
50
} from "@simplewebauthn/server/helpers";
51
```
52
53
## Basic Usage
54
55
**Complete Registration and Authentication Flow:**
56
57
```typescript
58
// === CLIENT SIDE (Browser) ===
59
import {
60
startRegistration,
61
startAuthentication,
62
browserSupportsWebAuthn
63
} from "@simplewebauthn/browser";
64
65
// Check WebAuthn support
66
if (!browserSupportsWebAuthn()) {
67
console.log("WebAuthn not supported");
68
return;
69
}
70
71
// Registration
72
const registrationOptions = await fetch("/webauthn/register/begin").then(r => r.json());
73
const registrationResponse = await startRegistration({
74
optionsJSON: registrationOptions,
75
});
76
await fetch("/webauthn/register/finish", {
77
method: "POST",
78
headers: { "Content-Type": "application/json" },
79
body: JSON.stringify(registrationResponse),
80
});
81
82
// Authentication
83
const authOptions = await fetch("/webauthn/authenticate/begin").then(r => r.json());
84
const authResponse = await startAuthentication({
85
optionsJSON: authOptions,
86
});
87
await fetch("/webauthn/authenticate/finish", {
88
method: "POST",
89
headers: { "Content-Type": "application/json" },
90
body: JSON.stringify(authResponse),
91
});
92
93
// === SERVER SIDE ===
94
import {
95
generateRegistrationOptions,
96
verifyRegistrationResponse,
97
generateAuthenticationOptions,
98
verifyAuthenticationResponse,
99
} from "@simplewebauthn/server";
100
101
// Registration endpoints
102
app.post('/webauthn/register/begin', async (req, res) => {
103
const options = await generateRegistrationOptions({
104
rpName: "My App",
105
rpID: "example.com",
106
userName: req.user.email,
107
userDisplayName: req.user.name,
108
});
109
req.session.challenge = options.challenge;
110
res.json(options);
111
});
112
113
app.post('/webauthn/register/finish', async (req, res) => {
114
const verification = await verifyRegistrationResponse({
115
response: req.body,
116
expectedChallenge: req.session.challenge,
117
expectedOrigin: "https://example.com",
118
});
119
120
if (verification.verified) {
121
// Save credential to database
122
res.json({ verified: true });
123
}
124
});
125
126
// Authentication endpoints
127
app.post('/webauthn/authenticate/begin', async (req, res) => {
128
const options = await generateAuthenticationOptions({
129
rpID: "example.com",
130
});
131
req.session.challenge = options.challenge;
132
res.json(options);
133
});
134
135
app.post('/webauthn/authenticate/finish', async (req, res) => {
136
const verification = await verifyAuthenticationResponse({
137
response: req.body,
138
expectedChallenge: req.session.challenge,
139
expectedOrigin: "https://example.com",
140
credential: storedCredential,
141
});
142
143
if (verification.verified) {
144
// User authenticated
145
res.json({ verified: true });
146
}
147
});
148
```
149
150
## Architecture
151
152
SimpleWebAuthn is built around several key components:
153
154
**Browser Package:**
155
- **Core WebAuthn Methods**: High-level `startRegistration` and `startAuthentication` functions
156
- **Browser Detection**: Capability detection for WebAuthn support and platform authenticators
157
- **Data Encoding Utilities**: Base64URL conversion for handling WebAuthn's ArrayBuffer data
158
- **Error Handling**: Comprehensive error classification with `WebAuthnError`
159
- **Abort Service**: Request management for concurrent WebAuthn operations
160
161
**Server Package:**
162
- **Options Generation**: Functions to create WebAuthn ceremony options
163
- **Response Verification**: Functions to verify client responses and attestations
164
- **Metadata Service**: FIDO Metadata Service integration for authenticator validation
165
- **Settings Service**: Configuration management for root certificates and attestation formats
166
- **Type System**: Complete TypeScript definitions for all WebAuthn interfaces
167
168
## Capabilities
169
170
### Browser Package Capabilities
171
172
#### WebAuthn Registration
173
Handles the complete WebAuthn registration flow on the client side.
174
175
```typescript { .api }
176
function startRegistration(options: {
177
optionsJSON: PublicKeyCredentialCreationOptionsJSON;
178
useAutoRegister?: boolean;
179
}): Promise<RegistrationResponseJSON>;
180
```
181
182
[WebAuthn Registration](./registration.md)
183
184
#### WebAuthn Authentication
185
Handles the complete WebAuthn authentication flow with support for conditional UI.
186
187
```typescript { .api }
188
function startAuthentication(options: {
189
optionsJSON: PublicKeyCredentialRequestOptionsJSON;
190
useBrowserAutofill?: boolean;
191
verifyBrowserAutofillInput?: boolean;
192
}): Promise<AuthenticationResponseJSON>;
193
```
194
195
[WebAuthn Authentication](./authentication.md)
196
197
#### Browser Support Detection
198
Functions to detect WebAuthn capabilities and browser support.
199
200
```typescript { .api }
201
function browserSupportsWebAuthn(): boolean;
202
function platformAuthenticatorIsAvailable(): Promise<boolean>;
203
function browserSupportsWebAuthnAutofill(): Promise<boolean>;
204
```
205
206
[Browser Support Detection](./browser-support.md)
207
208
#### Data Encoding Utilities
209
Utilities for converting between Base64URL strings and ArrayBuffers.
210
211
```typescript { .api }
212
function base64URLStringToBuffer(base64URLString: string): ArrayBuffer;
213
function bufferToBase64URLString(buffer: ArrayBuffer): string;
214
```
215
216
[Data Encoding Utilities](./data-encoding.md)
217
218
#### Error Handling and Services
219
Comprehensive error handling and abort service for managing operations.
220
221
```typescript { .api }
222
class WebAuthnError extends Error {
223
code: WebAuthnErrorCode;
224
constructor(options: {
225
message: string;
226
code: WebAuthnErrorCode;
227
cause: Error;
228
name?: string;
229
});
230
}
231
232
interface WebAuthnAbortService {
233
createNewAbortSignal(): AbortSignal;
234
cancelCeremony(): void;
235
}
236
```
237
238
[Error Handling and Services](./error-handling.md)
239
240
### Server Package Capabilities
241
242
#### Registration Options Generation
243
Server-side functions for generating WebAuthn registration options.
244
245
```typescript { .api }
246
function generateRegistrationOptions(options: {
247
rpName: string;
248
rpID: string;
249
userName: string;
250
userID?: Uint8Array;
251
challenge?: string | Uint8Array;
252
userDisplayName?: string;
253
timeout?: number;
254
attestationType?: 'direct' | 'enterprise' | 'none';
255
excludeCredentials?: {
256
id: Base64URLString;
257
transports?: AuthenticatorTransportFuture[];
258
}[];
259
authenticatorSelection?: AuthenticatorSelectionCriteria;
260
extensions?: AuthenticationExtensionsClientInputs;
261
supportedAlgorithmIDs?: COSEAlgorithmIdentifier[];
262
preferredAuthenticatorType?: 'securityKey' | 'localDevice' | 'remoteDevice';
263
}): Promise<PublicKeyCredentialCreationOptionsJSON>;
264
```
265
266
#### Registration Response Verification
267
Server-side functions for verifying WebAuthn registration responses.
268
269
```typescript { .api }
270
function verifyRegistrationResponse(options: {
271
response: RegistrationResponseJSON;
272
expectedChallenge: string | ((challenge: string) => boolean | Promise<boolean>);
273
expectedOrigin: string | string[];
274
expectedRPID?: string | string[];
275
expectedType?: string | string[];
276
requireUserPresence?: boolean;
277
requireUserVerification?: boolean;
278
supportedAlgorithmIDs?: COSEAlgorithmIdentifier[];
279
}): Promise<VerifiedRegistrationResponse>;
280
```
281
282
#### Authentication Options Generation
283
Server-side functions for generating WebAuthn authentication options.
284
285
```typescript { .api }
286
function generateAuthenticationOptions(options: {
287
rpID: string;
288
allowCredentials?: {
289
id: Base64URLString;
290
transports?: AuthenticatorTransportFuture[];
291
}[];
292
challenge?: string | Uint8Array;
293
timeout?: number;
294
userVerification?: 'required' | 'preferred' | 'discouraged';
295
extensions?: AuthenticationExtensionsClientInputs;
296
}): Promise<PublicKeyCredentialRequestOptionsJSON>;
297
```
298
299
#### Authentication Response Verification
300
Server-side functions for verifying WebAuthn authentication responses.
301
302
```typescript { .api }
303
function verifyAuthenticationResponse(options: {
304
response: AuthenticationResponseJSON;
305
expectedChallenge: string | ((challenge: string) => boolean | Promise<boolean>);
306
expectedOrigin: string | string[];
307
expectedRPID?: string | string[];
308
credential: {
309
id: Base64URLString;
310
publicKey: Uint8Array;
311
counter: number;
312
transports?: AuthenticatorTransportFuture[];
313
};
314
requireUserPresence?: boolean;
315
requireUserVerification?: boolean;
316
advancedFIDOConfig?: {
317
userVerification?: 'required' | 'preferred' | 'discouraged';
318
};
319
}): Promise<VerifiedAuthenticationResponse>;
320
```
321
322
#### Metadata and Settings Services
323
Services for managing authenticator metadata and root certificates.
324
325
```typescript { .api }
326
interface MetadataService {
327
initialize(options?: {
328
verificationMode?: VerificationMode;
329
mdsServers?: string[];
330
statements?: MetadataStatement[];
331
}): Promise<void>;
332
getStatement(aaguid: string): Promise<MetadataStatement | undefined>;
333
getStatements(): Promise<MetadataStatement[]>;
334
}
335
336
interface SettingsService {
337
setRootCertificates(opts: {
338
identifier: RootCertIdentifier;
339
certificates: (Uint8Array | string)[];
340
}): void;
341
getRootCertificates(opts: {
342
identifier: RootCertIdentifier;
343
}): string[];
344
}
345
```
346
347
[Server Package Documentation](./server.md)
348
349
## Types
350
351
### Response Types
352
353
```typescript { .api }
354
interface RegistrationResponseJSON {
355
id: Base64URLString;
356
rawId: Base64URLString;
357
response: AuthenticatorAttestationResponseJSON;
358
authenticatorAttachment?: AuthenticatorAttachment;
359
clientExtensionResults: AuthenticationExtensionsClientOutputs;
360
type: PublicKeyCredentialType;
361
}
362
363
interface AuthenticationResponseJSON {
364
id: Base64URLString;
365
rawId: Base64URLString;
366
response: AuthenticatorAssertionResponseJSON;
367
authenticatorAttachment?: AuthenticatorAttachment;
368
clientExtensionResults: AuthenticationExtensionsClientOutputs;
369
type: PublicKeyCredentialType;
370
}
371
```
372
373
### Options Types
374
375
```typescript { .api }
376
interface PublicKeyCredentialCreationOptionsJSON {
377
rp: PublicKeyCredentialRpEntity;
378
user: PublicKeyCredentialUserEntityJSON;
379
challenge: Base64URLString;
380
pubKeyCredParams: PublicKeyCredentialParameters[];
381
timeout?: number;
382
excludeCredentials?: PublicKeyCredentialDescriptorJSON[];
383
authenticatorSelection?: AuthenticatorSelectionCriteria;
384
hints?: PublicKeyCredentialHint[];
385
attestation?: AttestationConveyancePreference;
386
attestationFormats?: AttestationFormat[];
387
extensions?: AuthenticationExtensionsClientInputs;
388
}
389
390
interface PublicKeyCredentialRequestOptionsJSON {
391
challenge: Base64URLString;
392
timeout?: number;
393
rpId?: string;
394
allowCredentials?: PublicKeyCredentialDescriptorJSON[];
395
userVerification?: UserVerificationRequirement;
396
hints?: PublicKeyCredentialHint[];
397
extensions?: AuthenticationExtensionsClientInputs;
398
}
399
```
400
401
### Verification Response Types
402
403
```typescript { .api }
404
interface VerifiedRegistrationResponse {
405
verified: boolean;
406
registrationInfo?: {
407
fmt: AttestationFormat;
408
counter: number;
409
aaguid: string;
410
credentialID: Uint8Array;
411
credentialPublicKey: Uint8Array;
412
userVerified: boolean;
413
credentialDeviceType: CredentialDeviceType;
414
credentialBackedUp: boolean;
415
};
416
}
417
418
interface VerifiedAuthenticationResponse {
419
verified: boolean;
420
authenticationInfo?: {
421
newCounter: number;
422
userVerified: boolean;
423
credentialDeviceType: CredentialDeviceType;
424
credentialBackedUp: boolean;
425
};
426
}
427
```
428
429
### Utility Types
430
431
```typescript { .api }
432
type Base64URLString = string;
433
434
type AuthenticatorTransportFuture =
435
| 'ble'
436
| 'cable'
437
| 'hybrid'
438
| 'internal'
439
| 'nfc'
440
| 'smart-card'
441
| 'usb';
442
443
type WebAuthnErrorCode =
444
| 'ERROR_CEREMONY_ABORTED'
445
| 'ERROR_INVALID_DOMAIN'
446
| 'ERROR_INVALID_RP_ID'
447
| 'ERROR_INVALID_USER_ID_LENGTH'
448
| 'ERROR_MALFORMED_PUBKEYCREDPARAMS'
449
| 'ERROR_AUTHENTICATOR_GENERAL_ERROR'
450
| 'ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT'
451
| 'ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT'
452
| 'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED'
453
| 'ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG'
454
| 'ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE'
455
| 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY';
456
457
type CredentialDeviceType = 'singleDevice' | 'multiDevice';
458
459
type PublicKeyCredentialHint = 'hybrid' | 'security-key' | 'client-device';
460
461
type AttestationFormat =
462
| 'fido-u2f'
463
| 'packed'
464
| 'android-safetynet'
465
| 'android-key'
466
| 'tpm'
467
| 'apple'
468
| 'none';
469
470
type VerificationMode = 'permissive' | 'strict';
471
472
type RootCertIdentifier = AttestationFormat | 'mds';
473
```