@omni2fa/core 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/Interfaces/IOmni2Fa.d.ts +18 -0
  2. package/dist/Interfaces/IOmni2Fa.d.ts.map +1 -0
  3. package/dist/client/Interfaces/ClientCall.d.ts +5 -0
  4. package/dist/client/Interfaces/ClientCall.d.ts.map +1 -0
  5. package/dist/client/Interfaces/ClientCallError.d.ts +9 -0
  6. package/dist/client/Interfaces/ClientCallError.d.ts.map +1 -0
  7. package/dist/client/Interfaces/ClientCallResult.d.ts +6 -0
  8. package/dist/client/Interfaces/ClientCallResult.d.ts.map +1 -0
  9. package/dist/client/Interfaces/IOmni2FaClient.d.ts +26 -0
  10. package/dist/client/Interfaces/IOmni2FaClient.d.ts.map +1 -0
  11. package/dist/client/Omni2FaClient.d.ts +36 -0
  12. package/dist/client/Omni2FaClient.d.ts.map +1 -0
  13. package/dist/client/Omni2FaClientConfig.d.ts +20 -0
  14. package/dist/client/Omni2FaClientConfig.d.ts.map +1 -0
  15. package/dist/createOmni2Fa.d.ts +8 -0
  16. package/dist/createOmni2Fa.d.ts.map +1 -0
  17. package/dist/errors/Omni2FaApiError.d.ts +12 -0
  18. package/dist/errors/Omni2FaApiError.d.ts.map +1 -0
  19. package/dist/errors/codes.d.ts +20 -0
  20. package/dist/errors/codes.d.ts.map +1 -0
  21. package/dist/errors/messages.d.ts +2 -0
  22. package/dist/errors/messages.d.ts.map +1 -0
  23. package/dist/index.cjs +2 -0
  24. package/dist/index.cjs.map +1 -0
  25. package/dist/index.d.ts +39 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +915 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/machines/challenge/ChallengeContext.d.ts +16 -0
  30. package/dist/machines/challenge/ChallengeContext.d.ts.map +1 -0
  31. package/dist/machines/challenge/ChallengeEvent.d.ts +16 -0
  32. package/dist/machines/challenge/ChallengeEvent.d.ts.map +1 -0
  33. package/dist/machines/challenge/challengeMachine.d.ts +105 -0
  34. package/dist/machines/challenge/challengeMachine.d.ts.map +1 -0
  35. package/dist/machines/emailEnrollment/EmailEnrollmentContext.d.ts +15 -0
  36. package/dist/machines/emailEnrollment/EmailEnrollmentContext.d.ts.map +1 -0
  37. package/dist/machines/emailEnrollment/EmailEnrollmentEvent.d.ts +14 -0
  38. package/dist/machines/emailEnrollment/EmailEnrollmentEvent.d.ts.map +1 -0
  39. package/dist/machines/emailEnrollment/emailEnrollmentMachine.d.ts +71 -0
  40. package/dist/machines/emailEnrollment/emailEnrollmentMachine.d.ts.map +1 -0
  41. package/dist/machines/methods/MethodsContext.d.ts +8 -0
  42. package/dist/machines/methods/MethodsContext.d.ts.map +1 -0
  43. package/dist/machines/methods/MethodsEvent.d.ts +10 -0
  44. package/dist/machines/methods/MethodsEvent.d.ts.map +1 -0
  45. package/dist/machines/methods/methodsMachine.d.ts +43 -0
  46. package/dist/machines/methods/methodsMachine.d.ts.map +1 -0
  47. package/dist/machines/totpEnrollment/TotpEnrollmentContext.d.ts +12 -0
  48. package/dist/machines/totpEnrollment/TotpEnrollmentContext.d.ts.map +1 -0
  49. package/dist/machines/totpEnrollment/TotpEnrollmentEvent.d.ts +11 -0
  50. package/dist/machines/totpEnrollment/TotpEnrollmentEvent.d.ts.map +1 -0
  51. package/dist/machines/totpEnrollment/totpEnrollmentMachine.d.ts +50 -0
  52. package/dist/machines/totpEnrollment/totpEnrollmentMachine.d.ts.map +1 -0
  53. package/dist/machines/webauthnEnrollment/WebAuthnEnrollmentContext.d.ts +12 -0
  54. package/dist/machines/webauthnEnrollment/WebAuthnEnrollmentContext.d.ts.map +1 -0
  55. package/dist/machines/webauthnEnrollment/WebAuthnEnrollmentEvent.d.ts +10 -0
  56. package/dist/machines/webauthnEnrollment/WebAuthnEnrollmentEvent.d.ts.map +1 -0
  57. package/dist/machines/webauthnEnrollment/webauthnEnrollmentMachine.d.ts +47 -0
  58. package/dist/machines/webauthnEnrollment/webauthnEnrollmentMachine.d.ts.map +1 -0
  59. package/dist/storage/Interfaces/IStorage.d.ts +10 -0
  60. package/dist/storage/Interfaces/IStorage.d.ts.map +1 -0
  61. package/dist/storage/LocalStorageStorage.d.ts +8 -0
  62. package/dist/storage/LocalStorageStorage.d.ts.map +1 -0
  63. package/dist/storage/MemoryStorage.d.ts +9 -0
  64. package/dist/storage/MemoryStorage.d.ts.map +1 -0
  65. package/dist/storage/SessionStorageStorage.d.ts +8 -0
  66. package/dist/storage/SessionStorageStorage.d.ts.map +1 -0
  67. package/dist/types/api.d.ts +1075 -0
  68. package/dist/types/api.d.ts.map +1 -0
  69. package/dist/types/dtos.d.ts +29 -0
  70. package/dist/types/dtos.d.ts.map +1 -0
  71. package/dist/webauthn/base64url.d.ts +4 -0
  72. package/dist/webauthn/base64url.d.ts.map +1 -0
  73. package/dist/webauthn/ceremony.d.ts +5 -0
  74. package/dist/webauthn/ceremony.d.ts.map +1 -0
  75. package/package.json +62 -0
package/dist/index.js ADDED
@@ -0,0 +1,915 @@
1
+ import N from "openapi-fetch";
2
+ import { setup as h, fromPromise as l, createActor as u } from "xstate";
3
+ class k {
4
+ map = /* @__PURE__ */ new Map();
5
+ get(e) {
6
+ return this.map.get(e) ?? null;
7
+ }
8
+ set(e, r) {
9
+ this.map.set(e, r);
10
+ }
11
+ remove(e) {
12
+ this.map.delete(e);
13
+ }
14
+ }
15
+ const s = {
16
+ InvalidCode: "INVALID_CODE",
17
+ PreAuthExpired: "PREAUTH_EXPIRED",
18
+ PreAuthInvalid: "PREAUTH_INVALID",
19
+ ChallengeNotFound: "CHALLENGE_NOT_FOUND",
20
+ ChallengeConsumed: "CHALLENGE_CONSUMED",
21
+ TooManyAttempts: "TOO_MANY_ATTEMPTS",
22
+ MethodNotFound: "METHOD_NOT_FOUND",
23
+ TypeAlreadyEnrolled: "TYPE_ALREADY_ENROLLED",
24
+ MaxMethodsReached: "MAX_METHODS_REACHED",
25
+ LastMethodProtected: "LAST_METHOD_PROTECTED",
26
+ RecoveryCodeInvalid: "RECOVERY_CODE_INVALID",
27
+ RecoveryCodeUsed: "RECOVERY_CODE_USED",
28
+ WebAuthnVerificationFailed: "WEBAUTHN_VERIFICATION_FAILED",
29
+ ValidationFailed: "VALIDATION_FAILED",
30
+ NetworkError: "NETWORK_ERROR",
31
+ Unknown: "UNKNOWN"
32
+ }, w = {
33
+ [s.InvalidCode]: "The code you entered is invalid.",
34
+ [s.PreAuthExpired]: "Your session has expired. Please sign in again.",
35
+ [s.PreAuthInvalid]: "Your session is invalid. Please sign in again.",
36
+ [s.ChallengeNotFound]: "No active verification step. Please restart.",
37
+ [s.ChallengeConsumed]: "This verification step was already used. Please sign in again.",
38
+ [s.TooManyAttempts]: "Too many attempts. Please wait before trying again.",
39
+ [s.MethodNotFound]: "The selected 2FA method was not found.",
40
+ [s.TypeAlreadyEnrolled]: "You already have this type of 2FA enabled.",
41
+ [s.MaxMethodsReached]: "You have reached the maximum number of 2FA methods.",
42
+ [s.LastMethodProtected]: "You cannot remove your last 2FA method.",
43
+ [s.RecoveryCodeInvalid]: "The recovery code is invalid.",
44
+ [s.RecoveryCodeUsed]: "This recovery code has already been used.",
45
+ [s.WebAuthnVerificationFailed]: "Security key verification failed.",
46
+ [s.ValidationFailed]: "The request was malformed.",
47
+ [s.NetworkError]: "Network error. Please check your connection.",
48
+ [s.Unknown]: "An unexpected error occurred."
49
+ };
50
+ function v(t) {
51
+ return w[t] ?? w[s.Unknown];
52
+ }
53
+ const R = "omni2fa:preauth", D = "omni2fa:session", I = "http://omni2fa.local";
54
+ class P {
55
+ storage;
56
+ preAuthKey;
57
+ sessionKey;
58
+ basePath;
59
+ inner;
60
+ constructor(e) {
61
+ this.storage = e.storage ?? new k(), this.preAuthKey = e.preAuthStorageKey ?? R, this.sessionKey = e.sessionStorageKey ?? D, this.basePath = new URL(e.baseUrl, I).pathname.replace(/\/$/, ""), this.inner = N({
62
+ baseUrl: e.baseUrl,
63
+ fetch: e.fetch ?? globalThis.fetch.bind(globalThis),
64
+ ...e.credentials ? { credentials: e.credentials } : {}
65
+ }), this.inner.use({
66
+ onRequest: ({ request: r }) => {
67
+ if (r.headers.has("Authorization"))
68
+ return r;
69
+ const n = this.isPreAuthEndpoint(r.url) ? this.getPreAuthToken() : this.getSessionToken();
70
+ return n && r.headers.set("Authorization", `Bearer ${n}`), r;
71
+ }
72
+ });
73
+ }
74
+ /** Pre-auth endpoints are exactly the ones mounted under <c>{basePath}/challenge/</c>. */
75
+ isPreAuthEndpoint(e) {
76
+ const r = new URL(e, I).pathname;
77
+ return (r.startsWith(this.basePath) ? r.slice(this.basePath.length) : r).startsWith("/challenge/");
78
+ }
79
+ setPreAuthToken(e) {
80
+ this.setToken(this.preAuthKey, e);
81
+ }
82
+ getPreAuthToken() {
83
+ return this.storage.get(this.preAuthKey);
84
+ }
85
+ setSessionToken(e) {
86
+ this.setToken(this.sessionKey, e);
87
+ }
88
+ getSessionToken() {
89
+ return this.storage.get(this.sessionKey);
90
+ }
91
+ setToken(e, r) {
92
+ r === null || r.length === 0 ? this.storage.remove(e) : this.storage.set(e, r);
93
+ }
94
+ async listMethods() {
95
+ const { data: e, error: r, response: n } = await this.inner.GET("/methods");
96
+ return this.toCall(e, r, n);
97
+ }
98
+ async removeMethod(e) {
99
+ const { error: r, response: n } = await this.inner.DELETE("/methods/{methodId}", { params: { path: { methodId: e } } });
100
+ return r ? this.errorCall(r, n) : { ok: !0, value: void 0 };
101
+ }
102
+ async startTotpEnrollment() {
103
+ const { data: e, error: r, response: n } = await this.inner.POST("/enroll/totp/start");
104
+ return this.toCall(e, r, n);
105
+ }
106
+ async confirmTotpEnrollment(e) {
107
+ const { data: r, error: n, response: o } = await this.inner.POST("/enroll/totp/confirm", { body: e });
108
+ return this.toCall(r, n, o);
109
+ }
110
+ async startEmailEnrollment(e) {
111
+ const { data: r, error: n, response: o } = await this.inner.POST("/enroll/email/start", { body: e });
112
+ return this.toCall(r, n, o);
113
+ }
114
+ async confirmEmailEnrollment(e) {
115
+ const { data: r, error: n, response: o } = await this.inner.POST("/enroll/email/confirm", { body: e });
116
+ return this.toCall(r, n, o);
117
+ }
118
+ async resendEmailEnrollment(e) {
119
+ const { data: r, error: n, response: o } = await this.inner.POST("/enroll/email/resend", { body: e });
120
+ return this.toCall(r, n, o);
121
+ }
122
+ async startWebAuthnEnrollment() {
123
+ const { data: e, error: r, response: n } = await this.inner.POST("/enroll/webauthn/start");
124
+ return this.toCall(e, r, n);
125
+ }
126
+ async confirmWebAuthnEnrollment(e) {
127
+ const { data: r, error: n, response: o } = await this.inner.POST("/enroll/webauthn/confirm", { body: e });
128
+ return this.toCall(r, n, o);
129
+ }
130
+ async startChallenge(e) {
131
+ const { data: r, error: n, response: o } = await this.inner.POST("/challenge/start", { body: e });
132
+ return this.toCall(r, n, o);
133
+ }
134
+ async resendChallenge(e) {
135
+ const { data: r, error: n, response: o } = await this.inner.POST("/challenge/resend", { body: e });
136
+ return this.toCall(r, n, o);
137
+ }
138
+ async verifyChallenge(e) {
139
+ const { data: r, error: n, response: o } = await this.inner.POST("/challenge/verify", { body: e });
140
+ return this.toCall(r, n, o);
141
+ }
142
+ async verifyRecoveryCode(e) {
143
+ const { data: r, error: n, response: o } = await this.inner.POST("/challenge/recovery-code", { body: e });
144
+ return this.toCall(r, n, o);
145
+ }
146
+ async regenerateRecoveryCodes() {
147
+ const { data: e, error: r, response: n } = await this.inner.POST("/recovery-codes/regenerate");
148
+ return this.toCall(e, r, n);
149
+ }
150
+ toCall(e, r, n) {
151
+ return r !== void 0 ? this.errorCall(r, n) : e === void 0 ? {
152
+ ok: !1,
153
+ code: s.NetworkError,
154
+ message: v(s.NetworkError),
155
+ httpStatus: n.status
156
+ } : { ok: !0, value: e };
157
+ }
158
+ errorCall(e, r) {
159
+ const n = e.code || s.Unknown;
160
+ return {
161
+ ok: !1,
162
+ code: n,
163
+ message: e.message || v(n),
164
+ httpStatus: r.status,
165
+ details: e.details ?? null
166
+ };
167
+ }
168
+ }
169
+ class z {
170
+ get(e) {
171
+ return globalThis.sessionStorage?.getItem(e) ?? null;
172
+ }
173
+ set(e, r) {
174
+ globalThis.sessionStorage?.setItem(e, r);
175
+ }
176
+ remove(e) {
177
+ globalThis.sessionStorage?.removeItem(e);
178
+ }
179
+ }
180
+ class X {
181
+ get(e) {
182
+ return globalThis.localStorage?.getItem(e) ?? null;
183
+ }
184
+ set(e, r) {
185
+ globalThis.localStorage?.setItem(e, r);
186
+ }
187
+ remove(e) {
188
+ globalThis.localStorage?.removeItem(e);
189
+ }
190
+ }
191
+ class a extends Error {
192
+ code;
193
+ httpStatus;
194
+ details;
195
+ constructor(e, r, n, o = null) {
196
+ super(r), this.name = "Omni2FaApiError", this.code = e, this.httpStatus = n, this.details = o;
197
+ }
198
+ }
199
+ const U = {
200
+ enrollmentId: null,
201
+ otpAuthUri: null,
202
+ secret: null,
203
+ methodId: null,
204
+ recoveryCodes: null,
205
+ errorCode: null,
206
+ errorMessage: null
207
+ };
208
+ function _(t) {
209
+ return h({
210
+ types: {
211
+ context: {},
212
+ events: {}
213
+ },
214
+ actors: {
215
+ startEnrollment: l(async () => {
216
+ const e = await t.startTotpEnrollment();
217
+ if (!e.ok)
218
+ throw new a(e.code, e.message, e.httpStatus, e.details ?? null);
219
+ return e.value;
220
+ }),
221
+ confirmEnrollment: l(async ({ input: e }) => {
222
+ const r = await t.confirmTotpEnrollment({
223
+ enrollmentId: e.enrollmentId,
224
+ code: e.code,
225
+ name: e.name
226
+ });
227
+ if (!r.ok)
228
+ throw new a(r.code, r.message, r.httpStatus, r.details ?? null);
229
+ return r.value;
230
+ })
231
+ }
232
+ }).createMachine({
233
+ id: "totpEnrollment",
234
+ initial: "idle",
235
+ context: U,
236
+ states: {
237
+ idle: {
238
+ on: {
239
+ start: { target: "starting" }
240
+ }
241
+ },
242
+ starting: {
243
+ invoke: {
244
+ src: "startEnrollment",
245
+ onDone: {
246
+ target: "awaitingCode",
247
+ actions: ({ context: e, event: r }) => {
248
+ e.enrollmentId = r.output.enrollmentId, e.otpAuthUri = r.output.otpAuthUri, e.secret = r.output.secret, e.errorCode = null, e.errorMessage = null;
249
+ }
250
+ },
251
+ onError: {
252
+ target: "failed",
253
+ actions: ({ context: e, event: r }) => A(e, r.error)
254
+ }
255
+ }
256
+ },
257
+ awaitingCode: {
258
+ on: {
259
+ submit: { target: "confirming" },
260
+ reset: { target: "idle", actions: p }
261
+ }
262
+ },
263
+ confirming: {
264
+ invoke: {
265
+ src: "confirmEnrollment",
266
+ input: ({ context: e, event: r }) => {
267
+ if (r.type !== "submit") throw new Error("confirming requires submit event");
268
+ if (!e.enrollmentId) throw new Error("no enrollmentId");
269
+ return { enrollmentId: e.enrollmentId, code: r.code, name: r.name ?? null };
270
+ },
271
+ onDone: {
272
+ target: "enrolled",
273
+ actions: ({ context: e, event: r }) => {
274
+ e.methodId = r.output.methodId, e.recoveryCodes = r.output.recoveryCodes ?? null, e.errorCode = null, e.errorMessage = null;
275
+ }
276
+ },
277
+ onError: {
278
+ target: "awaitingCode",
279
+ actions: ({ context: e, event: r }) => A(e, r.error)
280
+ }
281
+ }
282
+ },
283
+ enrolled: {
284
+ on: {
285
+ reset: { target: "idle", actions: p }
286
+ }
287
+ },
288
+ failed: {
289
+ on: {
290
+ start: { target: "starting" },
291
+ reset: { target: "idle", actions: p }
292
+ }
293
+ }
294
+ }
295
+ });
296
+ }
297
+ function p({ context: t }) {
298
+ t.enrollmentId = null, t.otpAuthUri = null, t.secret = null, t.methodId = null, t.recoveryCodes = null, t.errorCode = null, t.errorMessage = null;
299
+ }
300
+ function A(t, e) {
301
+ e instanceof a ? (t.errorCode = e.code, t.errorMessage = e.message) : (t.errorCode = "UNKNOWN", t.errorMessage = e instanceof Error ? e.message : null);
302
+ }
303
+ const J = {
304
+ enrollmentId: null,
305
+ email: null,
306
+ expiresAt: null,
307
+ resendAvailableAt: null,
308
+ methodId: null,
309
+ recoveryCodes: null,
310
+ errorCode: null,
311
+ errorMessage: null
312
+ };
313
+ function F(t) {
314
+ return h({
315
+ types: {
316
+ context: {},
317
+ events: {}
318
+ },
319
+ actors: {
320
+ startEnrollment: l(async ({ input: e }) => {
321
+ const r = await t.startEmailEnrollment({ email: e.email });
322
+ if (!r.ok)
323
+ throw new a(r.code, r.message, r.httpStatus, r.details ?? null);
324
+ return r.value;
325
+ }),
326
+ resendEnrollment: l(async ({ input: e }) => {
327
+ const r = await t.resendEmailEnrollment({ enrollmentId: e.enrollmentId });
328
+ if (!r.ok)
329
+ throw new a(r.code, r.message, r.httpStatus, r.details ?? null);
330
+ return r.value;
331
+ }),
332
+ confirmEnrollment: l(async ({ input: e }) => {
333
+ const r = await t.confirmEmailEnrollment({
334
+ enrollmentId: e.enrollmentId,
335
+ code: e.code,
336
+ name: e.name
337
+ });
338
+ if (!r.ok)
339
+ throw new a(r.code, r.message, r.httpStatus, r.details ?? null);
340
+ return r.value;
341
+ })
342
+ }
343
+ }).createMachine({
344
+ id: "emailEnrollment",
345
+ initial: "idle",
346
+ context: J,
347
+ states: {
348
+ idle: {
349
+ on: {
350
+ start: { target: "starting" }
351
+ }
352
+ },
353
+ starting: {
354
+ entry: ({ context: e, event: r }) => {
355
+ r.type === "start" && (e.email = r.email);
356
+ },
357
+ invoke: {
358
+ src: "startEnrollment",
359
+ input: ({ context: e }) => {
360
+ if (!e.email) throw new Error("no email");
361
+ return { email: e.email };
362
+ },
363
+ onDone: {
364
+ target: "awaitingCode",
365
+ actions: ({ context: e, event: r }) => b(e, r.output)
366
+ },
367
+ onError: {
368
+ target: "failed",
369
+ actions: ({ context: e, event: r }) => y(e, r.error)
370
+ }
371
+ }
372
+ },
373
+ awaitingCode: {
374
+ on: {
375
+ submit: { target: "confirming" },
376
+ resend: { target: "resending" },
377
+ reset: { target: "idle", actions: f }
378
+ }
379
+ },
380
+ resending: {
381
+ invoke: {
382
+ src: "resendEnrollment",
383
+ input: ({ context: e }) => {
384
+ if (!e.enrollmentId) throw new Error("no enrollmentId");
385
+ return { enrollmentId: e.enrollmentId };
386
+ },
387
+ onDone: {
388
+ target: "awaitingCode",
389
+ actions: ({ context: e, event: r }) => b(e, r.output)
390
+ },
391
+ onError: {
392
+ target: "awaitingCode",
393
+ actions: ({ context: e, event: r }) => y(e, r.error)
394
+ }
395
+ }
396
+ },
397
+ confirming: {
398
+ invoke: {
399
+ src: "confirmEnrollment",
400
+ input: ({ context: e, event: r }) => {
401
+ if (r.type !== "submit") throw new Error("confirming requires submit event");
402
+ if (!e.enrollmentId) throw new Error("no enrollmentId");
403
+ return { enrollmentId: e.enrollmentId, code: r.code, name: r.name ?? null };
404
+ },
405
+ onDone: {
406
+ target: "enrolled",
407
+ actions: ({ context: e, event: r }) => {
408
+ e.methodId = r.output.methodId, e.recoveryCodes = r.output.recoveryCodes ?? null, e.errorCode = null, e.errorMessage = null;
409
+ }
410
+ },
411
+ onError: {
412
+ target: "awaitingCode",
413
+ actions: ({ context: e, event: r }) => y(e, r.error)
414
+ }
415
+ }
416
+ },
417
+ enrolled: {
418
+ on: {
419
+ reset: { target: "idle", actions: f }
420
+ }
421
+ },
422
+ failed: {
423
+ on: {
424
+ start: { target: "starting" },
425
+ reset: { target: "idle", actions: f }
426
+ }
427
+ }
428
+ }
429
+ });
430
+ }
431
+ function b(t, e) {
432
+ t.enrollmentId = e.enrollmentId, t.expiresAt = e.expiresAt, t.resendAvailableAt = e.resendAvailableAt, t.errorCode = null, t.errorMessage = null;
433
+ }
434
+ function f({ context: t }) {
435
+ t.enrollmentId = null, t.email = null, t.expiresAt = null, t.resendAvailableAt = null, t.methodId = null, t.recoveryCodes = null, t.errorCode = null, t.errorMessage = null;
436
+ }
437
+ function y(t, e) {
438
+ e instanceof a ? (t.errorCode = e.code, t.errorMessage = e.message) : (t.errorCode = "UNKNOWN", t.errorMessage = e instanceof Error ? e.message : null);
439
+ }
440
+ function g(t) {
441
+ const e = t.replace(/-/g, "+").replace(/_/g, "/"), r = e.padEnd(Math.ceil(e.length / 4) * 4, "="), n = atob(r), o = new Uint8Array(n.length);
442
+ for (let i = 0; i < n.length; i++)
443
+ o[i] = n.charCodeAt(i);
444
+ return o.buffer;
445
+ }
446
+ function d(t) {
447
+ const e = new Uint8Array(t);
448
+ let r = "";
449
+ for (const n of e)
450
+ r += String.fromCharCode(n);
451
+ return btoa(r).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
452
+ }
453
+ function O(t) {
454
+ return (t ?? []).map((e) => ({ ...e, id: g(e.id) }));
455
+ }
456
+ async function L(t) {
457
+ const e = JSON.parse(t), r = {
458
+ ...e,
459
+ challenge: g(e.challenge),
460
+ user: { ...e.user, id: g(e.user.id) },
461
+ excludeCredentials: O(e.excludeCredentials)
462
+ // Cast through unknown: the spread carries Fido2's index-signature fields the DOM type omits.
463
+ }, n = await navigator.credentials.create({ publicKey: r });
464
+ if (n === null)
465
+ throw new Error("WebAuthn registration produced no credential.");
466
+ const o = n.response;
467
+ return JSON.stringify({
468
+ id: n.id,
469
+ rawId: d(n.rawId),
470
+ type: n.type,
471
+ extensions: n.getClientExtensionResults(),
472
+ response: {
473
+ attestationObject: d(o.attestationObject),
474
+ clientDataJSON: d(o.clientDataJSON)
475
+ }
476
+ });
477
+ }
478
+ async function K(t) {
479
+ const e = JSON.parse(t), r = {
480
+ ...e,
481
+ challenge: g(e.challenge),
482
+ allowCredentials: O(e.allowCredentials)
483
+ }, n = await navigator.credentials.get({ publicKey: r });
484
+ if (n === null)
485
+ throw new Error("WebAuthn authentication produced no credential.");
486
+ const o = n.response;
487
+ return JSON.stringify({
488
+ id: n.id,
489
+ rawId: d(n.rawId),
490
+ type: n.type,
491
+ extensions: n.getClientExtensionResults(),
492
+ response: {
493
+ authenticatorData: d(o.authenticatorData),
494
+ clientDataJSON: d(o.clientDataJSON),
495
+ signature: d(o.signature),
496
+ userHandle: o.userHandle ? d(o.userHandle) : null
497
+ }
498
+ });
499
+ }
500
+ const W = {
501
+ enrollmentId: null,
502
+ optionsJson: null,
503
+ name: null,
504
+ methodId: null,
505
+ recoveryCodes: null,
506
+ errorCode: null,
507
+ errorMessage: null
508
+ };
509
+ function $(t) {
510
+ return h({
511
+ types: {
512
+ context: {},
513
+ events: {}
514
+ },
515
+ actors: {
516
+ startEnrollment: l(async () => {
517
+ const e = await t.startWebAuthnEnrollment();
518
+ if (!e.ok)
519
+ throw new a(e.code, e.message, e.httpStatus, e.details ?? null);
520
+ return e.value;
521
+ }),
522
+ registerAndConfirm: l(async ({ input: e }) => {
523
+ const r = await L(e.optionsJson), n = await t.confirmWebAuthnEnrollment({
524
+ enrollmentId: e.enrollmentId,
525
+ attestationResponseJson: r,
526
+ name: e.name
527
+ });
528
+ if (!n.ok)
529
+ throw new a(n.code, n.message, n.httpStatus, n.details ?? null);
530
+ return n.value;
531
+ })
532
+ }
533
+ }).createMachine({
534
+ id: "webauthnEnrollment",
535
+ initial: "idle",
536
+ context: W,
537
+ states: {
538
+ idle: {
539
+ on: {
540
+ start: { target: "starting" }
541
+ }
542
+ },
543
+ starting: {
544
+ entry: ({ context: e, event: r }) => {
545
+ r.type === "start" && (e.name = r.name ?? null);
546
+ },
547
+ invoke: {
548
+ src: "startEnrollment",
549
+ onDone: {
550
+ target: "registering",
551
+ actions: ({ context: e, event: r }) => {
552
+ e.enrollmentId = r.output.enrollmentId, e.optionsJson = r.output.optionsJson, e.errorCode = null, e.errorMessage = null;
553
+ }
554
+ },
555
+ onError: {
556
+ target: "failed",
557
+ actions: ({ context: e, event: r }) => M(e, r.error)
558
+ }
559
+ }
560
+ },
561
+ registering: {
562
+ invoke: {
563
+ src: "registerAndConfirm",
564
+ input: ({ context: e }) => {
565
+ if (!e.enrollmentId || !e.optionsJson) throw new Error("no pending enrollment");
566
+ return { enrollmentId: e.enrollmentId, optionsJson: e.optionsJson, name: e.name };
567
+ },
568
+ onDone: {
569
+ target: "enrolled",
570
+ actions: ({ context: e, event: r }) => {
571
+ e.methodId = r.output.methodId, e.recoveryCodes = r.output.recoveryCodes ?? null, e.errorCode = null, e.errorMessage = null;
572
+ }
573
+ },
574
+ onError: {
575
+ target: "failed",
576
+ actions: ({ context: e, event: r }) => M(e, r.error)
577
+ }
578
+ }
579
+ },
580
+ enrolled: {
581
+ on: {
582
+ reset: { target: "idle", actions: T }
583
+ }
584
+ },
585
+ failed: {
586
+ on: {
587
+ retry: { target: "starting" },
588
+ reset: { target: "idle", actions: T }
589
+ }
590
+ }
591
+ }
592
+ });
593
+ }
594
+ function T({ context: t }) {
595
+ t.enrollmentId = null, t.optionsJson = null, t.name = null, t.methodId = null, t.recoveryCodes = null, t.errorCode = null, t.errorMessage = null;
596
+ }
597
+ function M(t, e) {
598
+ e instanceof a ? (t.errorCode = e.code, t.errorMessage = e.message) : (t.errorCode = "UNKNOWN", t.errorMessage = e instanceof Error ? e.message : null);
599
+ }
600
+ const H = {
601
+ methodId: null,
602
+ methodType: null,
603
+ userId: null,
604
+ expiresAt: null,
605
+ resendAvailableAt: null,
606
+ optionsJson: null,
607
+ errorCode: null,
608
+ errorMessage: null
609
+ };
610
+ function Y(t) {
611
+ return h({
612
+ types: {
613
+ context: {},
614
+ events: {}
615
+ },
616
+ actors: {
617
+ startChallenge: l(async ({ input: e }) => {
618
+ const r = await t.startChallenge({ methodId: e.methodId });
619
+ if (!r.ok)
620
+ throw new a(r.code, r.message, r.httpStatus, r.details ?? null);
621
+ return r.value;
622
+ }),
623
+ resendChallenge: l(async ({ input: e }) => {
624
+ const r = await t.resendChallenge({ methodId: e.methodId });
625
+ if (!r.ok)
626
+ throw new a(r.code, r.message, r.httpStatus, r.details ?? null);
627
+ return r.value;
628
+ }),
629
+ verifyChallenge: l(async ({ input: e }) => {
630
+ const r = await t.verifyChallenge({ methodId: e.methodId, code: e.code });
631
+ if (!r.ok)
632
+ throw new a(r.code, r.message, r.httpStatus, r.details ?? null);
633
+ return r.value;
634
+ }),
635
+ assertChallenge: l(async ({ input: e }) => {
636
+ const r = await K(e.optionsJson), n = await t.verifyChallenge({ methodId: e.methodId, assertionResponseJson: r });
637
+ if (!n.ok)
638
+ throw new a(n.code, n.message, n.httpStatus, n.details ?? null);
639
+ return n.value;
640
+ }),
641
+ verifyRecoveryCode: l(async ({ input: e }) => {
642
+ const r = await t.verifyRecoveryCode({ recoveryCode: e.code });
643
+ if (!r.ok)
644
+ throw new a(r.code, r.message, r.httpStatus, r.details ?? null);
645
+ return r.value;
646
+ })
647
+ }
648
+ }).createMachine({
649
+ id: "challenge",
650
+ initial: "idle",
651
+ context: H,
652
+ states: {
653
+ idle: {
654
+ on: {
655
+ pick: { target: "starting" },
656
+ useRecoveryCode: { target: "verifyingRecovery" }
657
+ }
658
+ },
659
+ starting: {
660
+ entry: ({ context: e, event: r }) => {
661
+ r.type === "pick" && (e.methodId = r.methodId);
662
+ },
663
+ invoke: {
664
+ src: "startChallenge",
665
+ input: ({ context: e }) => {
666
+ if (!e.methodId) throw new Error("no methodId");
667
+ return { methodId: e.methodId };
668
+ },
669
+ onDone: [
670
+ {
671
+ guard: ({ event: e }) => e.output.type === "WebAuthn",
672
+ target: "asserting",
673
+ actions: ({ context: e, event: r }) => C(e, r.output)
674
+ },
675
+ {
676
+ target: "awaitingCode",
677
+ actions: ({ context: e, event: r }) => C(e, r.output)
678
+ }
679
+ ],
680
+ onError: {
681
+ target: "failed",
682
+ actions: ({ context: e, event: r }) => c(e, r.error)
683
+ }
684
+ }
685
+ },
686
+ asserting: {
687
+ invoke: {
688
+ src: "assertChallenge",
689
+ input: ({ context: e }) => {
690
+ if (!e.methodId || !e.optionsJson) throw new Error("no assertion options");
691
+ return { methodId: e.methodId, optionsJson: e.optionsJson };
692
+ },
693
+ onDone: {
694
+ target: "verified",
695
+ actions: ({ context: e, event: r }) => {
696
+ e.userId = r.output.userId, e.errorCode = null, e.errorMessage = null;
697
+ }
698
+ },
699
+ onError: {
700
+ target: "failed",
701
+ actions: ({ context: e, event: r }) => c(e, r.error)
702
+ }
703
+ }
704
+ },
705
+ awaitingCode: {
706
+ on: {
707
+ submit: { target: "verifying" },
708
+ resend: { target: "resending" },
709
+ useRecoveryCode: { target: "verifyingRecovery" },
710
+ reset: { target: "idle", actions: E }
711
+ }
712
+ },
713
+ verifyingRecovery: {
714
+ invoke: {
715
+ src: "verifyRecoveryCode",
716
+ input: ({ event: e }) => {
717
+ if (e.type !== "useRecoveryCode") throw new Error("verifyingRecovery requires useRecoveryCode event");
718
+ return { code: e.code };
719
+ },
720
+ onDone: {
721
+ target: "verified",
722
+ actions: ({ context: e, event: r }) => {
723
+ e.userId = r.output.userId, e.errorCode = null, e.errorMessage = null;
724
+ }
725
+ },
726
+ onError: {
727
+ target: "failed",
728
+ actions: ({ context: e, event: r }) => c(e, r.error)
729
+ }
730
+ }
731
+ },
732
+ resending: {
733
+ invoke: {
734
+ src: "resendChallenge",
735
+ input: ({ context: e }) => {
736
+ if (!e.methodId) throw new Error("no methodId");
737
+ return { methodId: e.methodId };
738
+ },
739
+ onDone: {
740
+ target: "awaitingCode",
741
+ actions: ({ context: e, event: r }) => C(e, r.output)
742
+ },
743
+ onError: {
744
+ target: "awaitingCode",
745
+ actions: ({ context: e, event: r }) => c(e, r.error)
746
+ }
747
+ }
748
+ },
749
+ verifying: {
750
+ invoke: {
751
+ src: "verifyChallenge",
752
+ input: ({ context: e, event: r }) => {
753
+ if (r.type !== "submit") throw new Error("verifying requires submit event");
754
+ if (!e.methodId) throw new Error("no methodId");
755
+ return { methodId: e.methodId, code: r.code };
756
+ },
757
+ onDone: {
758
+ target: "verified",
759
+ actions: ({ context: e, event: r }) => {
760
+ e.userId = r.output.userId, e.errorCode = null, e.errorMessage = null;
761
+ }
762
+ },
763
+ onError: {
764
+ target: "awaitingCode",
765
+ actions: ({ context: e, event: r }) => c(e, r.error)
766
+ }
767
+ }
768
+ },
769
+ verified: {
770
+ on: {
771
+ reset: { target: "idle", actions: E }
772
+ }
773
+ },
774
+ failed: {
775
+ on: {
776
+ pick: { target: "starting" },
777
+ useRecoveryCode: { target: "verifyingRecovery" },
778
+ reset: { target: "idle", actions: E }
779
+ }
780
+ }
781
+ }
782
+ });
783
+ }
784
+ function C(t, e) {
785
+ t.methodType = e.type, t.expiresAt = e.expiresAt ?? null, t.resendAvailableAt = e.resendAvailableAt ?? null, t.optionsJson = e.optionsJson ?? null, t.errorCode = null, t.errorMessage = null;
786
+ }
787
+ function E({ context: t }) {
788
+ t.methodId = null, t.methodType = null, t.userId = null, t.expiresAt = null, t.resendAvailableAt = null, t.optionsJson = null, t.errorCode = null, t.errorMessage = null;
789
+ }
790
+ function c(t, e) {
791
+ e instanceof a ? (t.errorCode = e.code, t.errorMessage = e.message) : (t.errorCode = "UNKNOWN", t.errorMessage = e instanceof Error ? e.message : null);
792
+ }
793
+ const V = {
794
+ items: [],
795
+ errorCode: null,
796
+ errorMessage: null
797
+ };
798
+ function B(t) {
799
+ return h({
800
+ types: {
801
+ context: {},
802
+ events: {}
803
+ },
804
+ actors: {
805
+ load: l(async () => {
806
+ const e = await t.listMethods();
807
+ if (!e.ok)
808
+ throw new a(e.code, e.message, e.httpStatus, e.details ?? null);
809
+ return e.value;
810
+ }),
811
+ remove: l(async ({ input: e }) => {
812
+ const r = await t.removeMethod(e.methodId);
813
+ if (!r.ok)
814
+ throw new a(r.code, r.message, r.httpStatus, r.details ?? null);
815
+ return e.methodId;
816
+ })
817
+ }
818
+ }).createMachine({
819
+ id: "methods",
820
+ initial: "idle",
821
+ context: V,
822
+ states: {
823
+ idle: {
824
+ on: {
825
+ load: { target: "loading" }
826
+ }
827
+ },
828
+ loading: {
829
+ invoke: {
830
+ src: "load",
831
+ onDone: {
832
+ target: "ready",
833
+ actions: ({ context: e, event: r }) => {
834
+ e.items = r.output, e.errorCode = null, e.errorMessage = null;
835
+ }
836
+ },
837
+ onError: {
838
+ target: "failed",
839
+ actions: ({ context: e, event: r }) => S(e, r.error)
840
+ }
841
+ }
842
+ },
843
+ ready: {
844
+ on: {
845
+ load: { target: "loading" },
846
+ remove: { target: "removing" }
847
+ }
848
+ },
849
+ removing: {
850
+ invoke: {
851
+ src: "remove",
852
+ input: ({ event: e }) => {
853
+ if (e.type !== "remove") throw new Error("removing requires remove event");
854
+ return { methodId: e.methodId };
855
+ },
856
+ onDone: {
857
+ target: "ready",
858
+ actions: ({ context: e, event: r }) => {
859
+ const n = r.output;
860
+ e.items = e.items.filter((o) => o.id !== n), e.errorCode = null, e.errorMessage = null;
861
+ }
862
+ },
863
+ onError: {
864
+ target: "ready",
865
+ actions: ({ context: e, event: r }) => S(e, r.error)
866
+ }
867
+ }
868
+ },
869
+ failed: {
870
+ on: {
871
+ load: { target: "loading" },
872
+ reset: { target: "idle", actions: G }
873
+ }
874
+ }
875
+ }
876
+ });
877
+ }
878
+ function G({ context: t }) {
879
+ t.items = [], t.errorCode = null, t.errorMessage = null;
880
+ }
881
+ function S(t, e) {
882
+ e instanceof a ? (t.errorCode = e.code, t.errorMessage = e.message) : (t.errorCode = "UNKNOWN", t.errorMessage = e instanceof Error ? e.message : null);
883
+ }
884
+ function Q(t) {
885
+ const e = new P(t), r = u(_(e)), n = u(F(e)), o = u($(e)), i = u(Y(e)), m = u(B(e));
886
+ return r.start(), n.start(), o.start(), i.start(), m.start(), {
887
+ client: e,
888
+ totpEnrollment: r,
889
+ emailEnrollment: n,
890
+ webauthnEnrollment: o,
891
+ challenge: i,
892
+ methods: m,
893
+ dispose() {
894
+ r.stop(), n.stop(), o.stop(), i.stop(), m.stop();
895
+ }
896
+ };
897
+ }
898
+ export {
899
+ X as LocalStorageStorage,
900
+ k as MemoryStorage,
901
+ a as Omni2FaApiError,
902
+ P as Omni2FaClient,
903
+ s as Omni2FaErrorCodes,
904
+ z as SessionStorageStorage,
905
+ Y as createChallengeMachine,
906
+ F as createEmailEnrollmentMachine,
907
+ B as createMethodsMachine,
908
+ Q as createOmni2Fa,
909
+ _ as createTotpEnrollmentMachine,
910
+ $ as createWebAuthnEnrollmentMachine,
911
+ v as getDefaultMessage,
912
+ K as startAuthentication,
913
+ L as startRegistration
914
+ };
915
+ //# sourceMappingURL=index.js.map