or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdbrowser-support.mddata-encoding.mderror-handling.mdindex.mdregistration.mdserver.md

error-handling.mddocs/

0

# Error Handling and Services

1

2

Comprehensive error handling with detailed error codes and abort service for managing concurrent WebAuthn operations. These utilities provide detailed error information and control over WebAuthn ceremony lifecycle.

3

4

## Capabilities

5

6

### WebAuthn Error Class

7

8

Custom Error class that provides nuanced error details for WebAuthn operations, helping developers understand and handle specific failure scenarios.

9

10

```typescript { .api }

11

/**

12

* A custom Error used to return a more nuanced error detailing _why_ one of the eight documented

13

* errors in the spec was raised after calling `navigator.credentials.create()` or

14

* `navigator.credentials.get()`:

15

*

16

* - `AbortError`

17

* - `ConstraintError`

18

* - `InvalidStateError`

19

* - `NotAllowedError`

20

* - `NotSupportedError`

21

* - `SecurityError`

22

* - `TypeError`

23

* - `UnknownError`

24

*/

25

class WebAuthnError extends Error {

26

code: WebAuthnErrorCode;

27

28

constructor(options: {

29

message: string;

30

code: WebAuthnErrorCode;

31

cause: Error;

32

name?: string;

33

});

34

}

35

```

36

37

**Usage Examples:**

38

39

```typescript

40

import { startRegistration, WebAuthnError } from "@simplewebauthn/browser";

41

42

try {

43

const response = await startRegistration({ optionsJSON });

44

} catch (error) {

45

if (error instanceof WebAuthnError) {

46

console.log(`WebAuthn Error: ${error.code}`);

47

console.log(`Message: ${error.message}`);

48

console.log(`Original error:`, error.cause);

49

50

// Handle specific error types

51

switch (error.code) {

52

case 'ERROR_CEREMONY_ABORTED':

53

console.log("User cancelled the operation");

54

break;

55

case 'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED':

56

console.log("This authenticator is already registered");

57

break;

58

case 'ERROR_INVALID_DOMAIN':

59

console.log("WebAuthn not allowed on this domain");

60

break;

61

default:

62

console.log("Unexpected WebAuthn error occurred");

63

}

64

} else {

65

console.error("Non-WebAuthn error:", error);

66

}

67

}

68

```

69

70

### WebAuthn Error Codes

71

72

Detailed error codes that provide specific information about WebAuthn failures.

73

74

```typescript { .api }

75

type WebAuthnErrorCode =

76

| 'ERROR_CEREMONY_ABORTED'

77

| 'ERROR_INVALID_DOMAIN'

78

| 'ERROR_INVALID_RP_ID'

79

| 'ERROR_INVALID_USER_ID_LENGTH'

80

| 'ERROR_MALFORMED_PUBKEYCREDPARAMS'

81

| 'ERROR_AUTHENTICATOR_GENERAL_ERROR'

82

| 'ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT'

83

| 'ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT'

84

| 'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED'

85

| 'ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG'

86

| 'ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE'

87

| 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY';

88

```

89

90

**Error Code Meanings:**

91

92

- `ERROR_CEREMONY_ABORTED`: User cancelled the WebAuthn operation

93

- `ERROR_INVALID_DOMAIN`: WebAuthn not allowed on the current domain

94

- `ERROR_INVALID_RP_ID`: Relying Party ID is invalid or mismatched

95

- `ERROR_INVALID_USER_ID_LENGTH`: User ID exceeds maximum allowed length

96

- `ERROR_MALFORMED_PUBKEYCREDPARAMS`: Invalid public key credential parameters

97

- `ERROR_AUTHENTICATOR_GENERAL_ERROR`: General authenticator hardware/software error

98

- `ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT`: Authenticator doesn't support resident/discoverable credentials

99

- `ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT`: Authenticator can't perform required user verification

100

- `ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED`: Attempting to register an already-registered authenticator

101

- `ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG`: No supported cryptographic algorithms

102

- `ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE`: Auto-registration failed user verification

103

- `ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY`: Error details are in the cause property

104

105

### WebAuthn Abort Service

106

107

Service singleton to ensure only a single WebAuthn ceremony is active at a time, preventing conflicts between concurrent operations.

108

109

```typescript { .api }

110

/**

111

* A service singleton to help ensure that only a single WebAuthn ceremony is active at a time.

112

*

113

* Users of **@simplewebauthn/browser** shouldn't typically need to use this, but it can help e.g.

114

* developers building projects that use client-side routing to better control the behavior of

115

* their UX in response to router navigation events.

116

*/

117

interface WebAuthnAbortService {

118

/**

119

* Prepare an abort signal that will help support multiple auth attempts without needing to

120

* reload the page. This is automatically called whenever `startRegistration()` and

121

* `startAuthentication()` are called.

122

*/

123

createNewAbortSignal(): AbortSignal;

124

125

/**

126

* Manually cancel any active WebAuthn registration or authentication attempt.

127

*/

128

cancelCeremony(): void;

129

}

130

131

// Exported as a singleton instance

132

const WebAuthnAbortService: WebAuthnAbortService;

133

```

134

135

**Usage Examples:**

136

137

```typescript

138

import { WebAuthnAbortService, startRegistration } from "@simplewebauthn/browser";

139

140

// Manual ceremony cancellation (advanced usage)

141

function setupCancelButton() {

142

const cancelButton = document.getElementById('cancel-webauthn');

143

cancelButton.addEventListener('click', () => {

144

WebAuthnAbortService.cancelCeremony();

145

console.log("WebAuthn ceremony cancelled");

146

});

147

}

148

149

// Router navigation cleanup (SPA usage)

150

function onRouteChange() {

151

// Cancel any ongoing WebAuthn operations when navigating

152

WebAuthnAbortService.cancelCeremony();

153

}

154

155

// The service is used automatically by startRegistration/startAuthentication

156

try {

157

// This automatically calls WebAuthnAbortService.createNewAbortSignal()

158

const response = await startRegistration({ optionsJSON });

159

} catch (error) {

160

if (error.name === 'AbortError') {

161

console.log("WebAuthn operation was aborted");

162

}

163

}

164

165

// Advanced: Manual abort signal creation

166

const abortSignal = WebAuthnAbortService.createNewAbortSignal();

167

console.log("New abort signal created for WebAuthn operation");

168

```

169

170

## Error Handling Patterns

171

172

### Basic Error Handling

173

174

```typescript

175

import { startRegistration, startAuthentication, WebAuthnError } from "@simplewebauthn/browser";

176

177

async function handleWebAuthnRegistration(options) {

178

try {

179

const response = await startRegistration({ optionsJSON: options });

180

return { success: true, data: response };

181

} catch (error) {

182

if (error instanceof WebAuthnError) {

183

return {

184

success: false,

185

error: error.code,

186

message: error.message

187

};

188

}

189

return {

190

success: false,

191

error: 'UNKNOWN_ERROR',

192

message: error.message

193

};

194

}

195

}

196

```

197

198

### User-Friendly Error Messages

199

200

```typescript

201

function getErrorMessage(error: WebAuthnError): string {

202

switch (error.code) {

203

case 'ERROR_CEREMONY_ABORTED':

204

return "Authentication was cancelled. Please try again.";

205

case 'ERROR_INVALID_DOMAIN':

206

return "Authentication is not allowed on this website.";

207

case 'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED':

208

return "This security key has already been registered.";

209

case 'ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT':

210

return "Your security key doesn't support the required verification method.";

211

case 'ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG':

212

return "Your security key doesn't support the required encryption methods.";

213

default:

214

return "An unexpected error occurred during authentication.";

215

}

216

}

217

218

// Usage

219

try {

220

await startRegistration({ optionsJSON });

221

} catch (error) {

222

if (error instanceof WebAuthnError) {

223

showUserError(getErrorMessage(error));

224

}

225

}

226

```

227

228

### Retry Logic with Error Handling

229

230

```typescript

231

async function retryableWebAuthnOperation(operationFn, maxRetries = 3) {

232

for (let attempt = 1; attempt <= maxRetries; attempt++) {

233

try {

234

return await operationFn();

235

} catch (error) {

236

if (error instanceof WebAuthnError) {

237

// Don't retry certain errors

238

const nonRetryableErrors = [

239

'ERROR_INVALID_DOMAIN',

240

'ERROR_INVALID_RP_ID',

241

'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED',

242

];

243

244

if (nonRetryableErrors.includes(error.code)) {

245

throw error; // Don't retry these

246

}

247

248

if (attempt === maxRetries) {

249

throw error; // Final attempt failed

250

}

251

252

console.log(`Attempt ${attempt} failed: ${error.code}, retrying...`);

253

await new Promise(resolve => setTimeout(resolve, 1000 * attempt));

254

} else {

255

throw error; // Non-WebAuthn errors aren't retryable

256

}

257

}

258

}

259

}

260

261

// Usage

262

try {

263

const response = await retryableWebAuthnOperation(() =>

264

startRegistration({ optionsJSON })

265

);

266

} catch (error) {

267

console.error("All retry attempts failed:", error);

268

}

269

```

270

271

## Service Integration

272

273

The abort service integrates seamlessly with the main WebAuthn functions:

274

275

```typescript

276

import { startRegistration, startAuthentication, WebAuthnAbortService } from "@simplewebauthn/browser";

277

278

// Both functions automatically use the abort service

279

const registrationPromise = startRegistration({ optionsJSON: regOptions });

280

const authenticationPromise = startAuthentication({ optionsJSON: authOptions });

281

282

// If you start a new operation, the previous one is automatically cancelled

283

// This prevents conflicts and ensures only one ceremony runs at a time

284

285

// Manual cancellation is available for advanced use cases

286

document.getElementById('cancel').addEventListener('click', () => {

287

WebAuthnAbortService.cancelCeremony();

288

});

289

```

290

291

This service is particularly useful in single-page applications where users might navigate between pages or trigger multiple authentication attempts.