@metamask-previews/profile-sync-controller 32.1.1-preview-c6cdff1dd → 32.1.1-preview-9d2a9bdf5

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 (63) hide show
  1. package/CHANGELOG.md +0 -2
  2. package/dist/controllers/authentication/AuthenticationController.d.ts.map +1 -1
  3. package/dist/controllers/authentication/AuthenticationController.js +5 -6
  4. package/dist/controllers/authentication/AuthenticationController.js.map +1 -1
  5. package/dist/controllers/user-storage/UserStorageController.d.ts.map +1 -1
  6. package/dist/controllers/user-storage/UserStorageController.js +5 -6
  7. package/dist/controllers/user-storage/UserStorageController.js.map +1 -1
  8. package/dist/sdk/authentication-jwt-bearer/flow-srp.d.ts +1 -56
  9. package/dist/sdk/authentication-jwt-bearer/flow-srp.d.ts.map +1 -1
  10. package/dist/sdk/authentication-jwt-bearer/flow-srp.js +1 -119
  11. package/dist/sdk/authentication-jwt-bearer/flow-srp.js.map +1 -1
  12. package/dist/sdk/authentication.d.ts +6 -15
  13. package/dist/sdk/authentication.d.ts.map +1 -1
  14. package/dist/sdk/authentication.js +0 -24
  15. package/dist/sdk/authentication.js.map +1 -1
  16. package/dist/sdk/constants.d.ts +0 -2
  17. package/dist/sdk/constants.d.ts.map +1 -1
  18. package/dist/sdk/constants.js +0 -2
  19. package/dist/sdk/constants.js.map +1 -1
  20. package/dist/sdk/errors.d.ts +0 -91
  21. package/dist/sdk/errors.d.ts.map +1 -1
  22. package/dist/sdk/errors.js +0 -161
  23. package/dist/sdk/errors.js.map +1 -1
  24. package/dist/sdk/index.d.ts +0 -3
  25. package/dist/sdk/index.d.ts.map +1 -1
  26. package/dist/sdk/index.js +0 -1
  27. package/dist/sdk/index.js.map +1 -1
  28. package/dist/sdk/mocks/auth.d.ts +0 -63
  29. package/dist/sdk/mocks/auth.d.ts.map +1 -1
  30. package/dist/sdk/mocks/auth.js +0 -90
  31. package/dist/sdk/mocks/auth.js.map +1 -1
  32. package/dist/sdk/utils/validate-login-response.d.ts.map +1 -1
  33. package/dist/sdk/utils/validate-login-response.js +7 -5
  34. package/dist/sdk/utils/validate-login-response.js.map +1 -1
  35. package/dist/shared/utils/entropy-source.d.ts +12 -3
  36. package/dist/shared/utils/entropy-source.d.ts.map +1 -1
  37. package/dist/shared/utils/entropy-source.js +17 -4
  38. package/dist/shared/utils/entropy-source.js.map +1 -1
  39. package/package.json +1 -3
  40. package/dist/sdk/authentication-jwt-bearer/mfa/schemas.d.ts +0 -691
  41. package/dist/sdk/authentication-jwt-bearer/mfa/schemas.d.ts.map +0 -1
  42. package/dist/sdk/authentication-jwt-bearer/mfa/schemas.js +0 -265
  43. package/dist/sdk/authentication-jwt-bearer/mfa/schemas.js.map +0 -1
  44. package/dist/sdk/authentication-jwt-bearer/mfa/services.d.ts +0 -104
  45. package/dist/sdk/authentication-jwt-bearer/mfa/services.d.ts.map +0 -1
  46. package/dist/sdk/authentication-jwt-bearer/mfa/services.js +0 -363
  47. package/dist/sdk/authentication-jwt-bearer/mfa/services.js.map +0 -1
  48. package/dist/sdk/authentication-jwt-bearer/mfa/types.d.ts +0 -125
  49. package/dist/sdk/authentication-jwt-bearer/mfa/types.d.ts.map +0 -1
  50. package/dist/sdk/authentication-jwt-bearer/mfa/types.js +0 -3
  51. package/dist/sdk/authentication-jwt-bearer/mfa/types.js.map +0 -1
  52. package/dist/sdk/utils/as-record.d.ts +0 -10
  53. package/dist/sdk/utils/as-record.d.ts.map +0 -1
  54. package/dist/sdk/utils/as-record.js +0 -14
  55. package/dist/sdk/utils/as-record.js.map +0 -1
  56. package/dist/sdk/utils/jwt.d.ts +0 -13
  57. package/dist/sdk/utils/jwt.d.ts.map +0 -1
  58. package/dist/sdk/utils/jwt.js +0 -21
  59. package/dist/sdk/utils/jwt.js.map +0 -1
  60. package/dist/sdk/utils/to-error-message.d.ts +0 -8
  61. package/dist/sdk/utils/to-error-message.d.ts.map +0 -1
  62. package/dist/sdk/utils/to-error-message.js +0 -10
  63. package/dist/sdk/utils/to-error-message.js.map +0 -1
@@ -1,363 +0,0 @@
1
- import log from 'loglevel';
2
- import { getEnvUrls } from '../../../shared/env.js';
3
- import { HTTP_STATUS_CODES } from '../../constants.js';
4
- import { CredentialAlreadyEnrolledError, CredentialNotEnrolledError, MaxIdentifiersReachedError, MaxPasskeysReachedError, MfaError, MfaFlowExpiredError, MfaIdentityMissingError, MfaRateLimitedError, MfaUnavailableError, MfaVerificationFailedError, OtpResendCooldownError, TooManyAttemptsError, } from '../../errors.js';
5
- import { asRecord } from '../../utils/as-record.js';
6
- import { toErrorMessage } from '../../utils/to-error-message.js';
7
- import { AuthenticationResponseJSONStruct, MfaCredentialsResponseStruct, MfaEnrollCompleteResponseStruct, MfaEnrollResponseStruct, MfaErrorResponseStruct, MfaVerifyCompleteResponseStruct, MfaVerifyResponseStruct, PasskeyCreateDataStruct, PasskeyRequestDataStruct, RegistrationResponseJSONStruct, assertValidMfaRequest, assertValidMfaResponse, } from './schemas.js';
8
- export const MFA_ENROLL_URL = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/mfa/enroll`;
9
- export const MFA_ENROLL_COMPLETE_URL = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/mfa/enroll/complete`;
10
- export const MFA_VERIFY_URL = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/mfa/verify`;
11
- export const MFA_VERIFY_COMPLETE_URL = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/mfa/verify/complete`;
12
- export const MFA_CREDENTIALS_URL = (env) => `${getEnvUrls(env).authApiUrl}/api/v2/mfa/credentials`;
13
- /**
14
- * Reads a credential's enrollment date. Unlike flow deadlines, this is display
15
- * metadata, so an unparsable value is dropped instead of rejecting the whole
16
- * credential list.
17
- *
18
- * @param value - The raw `enrolled_at` value, if the server sent one.
19
- * @returns The epoch milliseconds, or undefined when absent or unparsable.
20
- */
21
- function parseEnrolledAt(value) {
22
- if (!value) {
23
- return undefined;
24
- }
25
- const enrolledAt = Date.parse(value);
26
- if (Number.isNaN(enrolledAt)) {
27
- log.warn(`Ignoring unparsable MFA credential enrolled_at: ${value}`);
28
- return undefined;
29
- }
30
- return enrolledAt;
31
- }
32
- function parseExpiresAt(value) {
33
- const expiresAt = Date.parse(value);
34
- if (Number.isNaN(expiresAt)) {
35
- throw new MfaError('invalid_response', `Invalid expires_at: ${value}`);
36
- }
37
- return expiresAt;
38
- }
39
- /**
40
- * Parses passkey creation data embedded in an enrollment response.
41
- *
42
- * @param value - JSON-encoded creation options.
43
- * @returns Validated public-key creation options.
44
- */
45
- export function parsePasskeyCreateData(value) {
46
- try {
47
- const parsed = JSON.parse(value);
48
- assertValidMfaResponse(parsed, PasskeyCreateDataStruct);
49
- return parsed.publicKey;
50
- }
51
- catch (error) {
52
- if (error instanceof MfaError) {
53
- throw error;
54
- }
55
- const message = toErrorMessage(error);
56
- throw new MfaError('invalid_response', message);
57
- }
58
- }
59
- /**
60
- * Parses passkey request data embedded in a verification response.
61
- *
62
- * @param value - JSON-encoded request options.
63
- * @returns Validated public-key request options.
64
- */
65
- export function parsePasskeyRequestData(value) {
66
- try {
67
- const parsed = JSON.parse(value);
68
- assertValidMfaResponse(parsed, PasskeyRequestDataStruct);
69
- return parsed.publicKey;
70
- }
71
- catch (error) {
72
- if (error instanceof MfaError) {
73
- throw error;
74
- }
75
- const message = toErrorMessage(error);
76
- throw new MfaError('invalid_response', message);
77
- }
78
- }
79
- /**
80
- * Reads a `Retry-After` header as a delay. The human-readable error message is
81
- * deliberately not parsed: the API documents it as unstable.
82
- *
83
- * @param response - The throttled response.
84
- * @returns The delay in milliseconds, or undefined without a usable header.
85
- */
86
- function parseRetryAfter(response) {
87
- const header = response.headers.get('Retry-After');
88
- if (!header) {
89
- return undefined;
90
- }
91
- const seconds = Number(header);
92
- if (Number.isInteger(seconds)) {
93
- return Math.max(0, seconds * 1000);
94
- }
95
- const date = Date.parse(header);
96
- return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());
97
- }
98
- /**
99
- * Reads and validates the JSON error body of a failed MFA request.
100
- *
101
- * When the body parses as JSON but does not match the documented error
102
- * shape, a `message` field is salvaged if present so callers still get a
103
- * useful diagnostic instead of a content-free fallback.
104
- *
105
- * @param response - The failed response.
106
- * @returns The validated error body, a best-effort salvage of it, or
107
- * undefined when the body could not be parsed as JSON at all.
108
- */
109
- async function readErrorBody(response) {
110
- let body;
111
- try {
112
- body = await response.json();
113
- }
114
- catch {
115
- return undefined;
116
- }
117
- try {
118
- assertValidMfaResponse(body, MfaErrorResponseStruct);
119
- return body;
120
- }
121
- catch {
122
- const message = asRecord(body)?.message;
123
- return typeof message === 'string' ? { message } : undefined;
124
- }
125
- }
126
- async function throwMfaError(response, errorPrefix) {
127
- const { status } = response;
128
- const body = await readErrorBody(response);
129
- const message = `${errorPrefix}: ${body?.message ?? `HTTP ${status}`}`;
130
- // Status-only classification first: gateways and load balancers answer
131
- // 401/429/502 without the service's JSON body, and the caller still needs
132
- // to invalidate its session, honour Retry-After, or back off.
133
- if (status === HTTP_STATUS_CODES.UNAUTHORIZED) {
134
- throw new MfaError('authentication_required', message, { status });
135
- }
136
- const code = body?.code;
137
- switch (code) {
138
- case 'credential_already_enrolled':
139
- case 'email_already_enrolled':
140
- throw new CredentialAlreadyEnrolledError(code, message, status);
141
- case 'credential_not_enrolled':
142
- throw new CredentialNotEnrolledError(message, status);
143
- case 'flow_expired':
144
- case 'invalid_flow':
145
- throw new MfaFlowExpiredError(code, message, status);
146
- case 'mfa_identity_missing':
147
- throw new MfaIdentityMissingError(message, status);
148
- case 'invalid_code':
149
- case 'invalid_attestation':
150
- case 'invalid_assertion':
151
- throw new MfaVerificationFailedError(code, message, status);
152
- case 'too_many_attempts':
153
- throw new TooManyAttemptsError(message, status);
154
- case 'max_passkeys_reached':
155
- throw new MaxPasskeysReachedError(message, status);
156
- case 'max_identifiers_reached':
157
- throw new MaxIdentifiersReachedError(message, status);
158
- case 'otp_resend_cooldown':
159
- throw new OtpResendCooldownError(message, parseRetryAfter(response), status);
160
- case 'kratos_unavailable':
161
- throw new MfaUnavailableError(message, status);
162
- default:
163
- break;
164
- }
165
- if (status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {
166
- throw new MfaRateLimitedError(message, parseRetryAfter(response), status);
167
- }
168
- if (status === HTTP_STATUS_CODES.BAD_GATEWAY) {
169
- throw new MfaUnavailableError(message, status);
170
- }
171
- if (!body) {
172
- throw new MfaError('invalid_response', `${errorPrefix}: Unexpected error response (HTTP ${status})`, { status });
173
- }
174
- throw new MfaError(code ?? 'server_error', message, { status });
175
- }
176
- async function requestJson(url, accessToken, init) {
177
- let response;
178
- try {
179
- response = await fetch(url, {
180
- method: init?.method ?? 'GET',
181
- headers: {
182
- Authorization: `Bearer ${accessToken}`,
183
- ...(init?.body === undefined
184
- ? {}
185
- : { 'Content-Type': 'application/json' }),
186
- },
187
- ...(init?.body === undefined ? {} : { body: JSON.stringify(init.body) }),
188
- });
189
- }
190
- catch (error) {
191
- const message = toErrorMessage(error);
192
- throw new MfaUnavailableError(`MFA request failed: ${message}`);
193
- }
194
- if (!response.ok) {
195
- return await throwMfaError(response, 'MFA request failed');
196
- }
197
- try {
198
- return await response.json();
199
- }
200
- catch (error) {
201
- const message = toErrorMessage(error);
202
- throw new MfaError('invalid_response', message, {
203
- status: response.status,
204
- });
205
- }
206
- }
207
- /**
208
- * Begins enrollment of an MFA credential.
209
- *
210
- * @param env - Authentication environment.
211
- * @param accessToken - Primary profile access token.
212
- * @param body - Enrollment request.
213
- * @returns Validated enrollment flow data.
214
- */
215
- export async function mfaEnroll(env, accessToken, body) {
216
- const json = await requestJson(MFA_ENROLL_URL(env), accessToken, {
217
- method: 'POST',
218
- body,
219
- });
220
- assertValidMfaResponse(json, MfaEnrollResponseStruct);
221
- return {
222
- flowId: json.flow_id,
223
- expiresAt: parseExpiresAt(json.expires_at),
224
- ...(json.passkey_create_data
225
- ? { publicKey: parsePasskeyCreateData(json.passkey_create_data) }
226
- : {}),
227
- };
228
- }
229
- /**
230
- * Completes enrollment of an MFA credential.
231
- *
232
- * @param env - Authentication environment.
233
- * @param accessToken - Primary profile access token.
234
- * @param params - Flow identifier and enrollment proof.
235
- */
236
- export async function mfaEnrollComplete(env, accessToken, params) {
237
- let body = {
238
- credential_type: params.credential_type,
239
- flow_id: params.flow_id,
240
- ...(params.otp_code ? { otp_code: params.otp_code } : {}),
241
- };
242
- if (params.passkey_attestation) {
243
- assertValidMfaRequest(params.passkey_attestation, RegistrationResponseJSONStruct);
244
- body = {
245
- ...body,
246
- passkey_attestation: JSON.stringify(params.passkey_attestation),
247
- };
248
- }
249
- const json = await requestJson(MFA_ENROLL_COMPLETE_URL(env), accessToken, {
250
- method: 'POST',
251
- body,
252
- });
253
- assertValidMfaResponse(json, MfaEnrollCompleteResponseStruct);
254
- }
255
- /**
256
- * Begins step-up verification with an enrolled credential.
257
- *
258
- * @param env - Authentication environment.
259
- * @param accessToken - Primary profile access token.
260
- * @param body - Verification request.
261
- * @returns Validated verification flow data.
262
- */
263
- export async function mfaVerify(env, accessToken, body) {
264
- const json = await requestJson(MFA_VERIFY_URL(env), accessToken, {
265
- method: 'POST',
266
- body,
267
- });
268
- assertValidMfaResponse(json, MfaVerifyResponseStruct);
269
- return {
270
- flowId: json.flow_id,
271
- expiresAt: parseExpiresAt(json.expires_at),
272
- ...(json.passkey_request_data
273
- ? { publicKey: parsePasskeyRequestData(json.passkey_request_data) }
274
- : {}),
275
- };
276
- }
277
- /**
278
- * Completes step-up verification with an enrolled credential.
279
- *
280
- * @param env - Authentication environment.
281
- * @param accessToken - Primary profile access token.
282
- * @param params - Flow identifier and verification proof.
283
- * @returns The AAL2 assertion JWT and its lifetime in seconds.
284
- */
285
- export async function mfaVerifyComplete(env, accessToken, params) {
286
- let body = {
287
- credential_type: params.credential_type,
288
- flow_id: params.flow_id,
289
- ...(params.otp_code ? { otp_code: params.otp_code } : {}),
290
- };
291
- if (params.passkey_assertion) {
292
- assertValidMfaRequest(params.passkey_assertion, AuthenticationResponseJSONStruct);
293
- body = {
294
- ...body,
295
- passkey_assertion: JSON.stringify(params.passkey_assertion),
296
- };
297
- }
298
- const json = await requestJson(MFA_VERIFY_COMPLETE_URL(env), accessToken, {
299
- method: 'POST',
300
- body,
301
- });
302
- assertValidMfaResponse(json, MfaVerifyCompleteResponseStruct);
303
- return { token: json.token, expiresIn: json.expires_in };
304
- }
305
- function isSupportedStatus(status) {
306
- return status === 'active' || status === 'pending';
307
- }
308
- /**
309
- * Maps a server credential to its public controller representation.
310
- *
311
- * Unknown credential types or statuses are dropped so the server can extend
312
- * either without invalidating the whole list.
313
- *
314
- * @param credential - Validated server credential.
315
- * @returns A supported credential, or null when it cannot be represented.
316
- */
317
- export function toEnrolledCredential(credential) {
318
- const { credential_type: type, status } = credential;
319
- if (!isSupportedStatus(status)) {
320
- log.warn(`Ignoring MFA credential with unsupported status: ${status}`);
321
- return null;
322
- }
323
- const enrolledAt = parseEnrolledAt(credential.enrolled_at);
324
- const base = {
325
- status,
326
- ...(enrolledAt === undefined ? {} : { enrolledAt }),
327
- };
328
- if (type === 'passkey') {
329
- return {
330
- type,
331
- ...base,
332
- ...(credential.passkey?.display_name
333
- ? { displayName: credential.passkey.display_name }
334
- : {}),
335
- };
336
- }
337
- if (type === 'email_otp' && credential.email?.address !== undefined) {
338
- return {
339
- type,
340
- ...base,
341
- email: credential.email.address,
342
- // The spec marks `verified` optional; an active row is verified.
343
- verified: credential.email.verified ?? status === 'active',
344
- };
345
- }
346
- log.warn(`Ignoring unsupported or incomplete MFA credential: ${type}`);
347
- return null;
348
- }
349
- /**
350
- * Gets the credentials enrolled on the canonical profile.
351
- *
352
- * @param env - Authentication environment.
353
- * @param accessToken - Primary profile access token.
354
- * @returns Supported enrolled credentials.
355
- */
356
- export async function getMfaCredentials(env, accessToken) {
357
- const json = await requestJson(MFA_CREDENTIALS_URL(env), accessToken);
358
- assertValidMfaResponse(json, MfaCredentialsResponseStruct);
359
- return json.credentials
360
- .map(toEnrolledCredential)
361
- .filter((credential) => Boolean(credential));
362
- }
363
- //# sourceMappingURL=services.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"services.js","sourceRoot":"","sources":["../../../../src/sdk/authentication-jwt-bearer/mfa/services.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Json } from '@metamask/utils';\nimport log from 'loglevel';\n\nimport type { Env } from '../../../shared/env.js';\nimport { getEnvUrls } from '../../../shared/env.js';\nimport { HTTP_STATUS_CODES } from '../../constants.js';\nimport {\n CredentialAlreadyEnrolledError,\n CredentialNotEnrolledError,\n MaxIdentifiersReachedError,\n MaxPasskeysReachedError,\n MfaError,\n MfaFlowExpiredError,\n MfaIdentityMissingError,\n MfaRateLimitedError,\n MfaUnavailableError,\n MfaVerificationFailedError,\n OtpResendCooldownError,\n TooManyAttemptsError,\n} from '../../errors.js';\nimport { asRecord } from '../../utils/as-record.js';\nimport { toErrorMessage } from '../../utils/to-error-message.js';\nimport {\n AuthenticationResponseJSONStruct,\n MfaCredentialsResponseStruct,\n MfaEnrollCompleteResponseStruct,\n MfaEnrollResponseStruct,\n MfaErrorResponseStruct,\n MfaVerifyCompleteResponseStruct,\n MfaVerifyResponseStruct,\n PasskeyCreateDataStruct,\n PasskeyRequestDataStruct,\n RegistrationResponseJSONStruct,\n assertValidMfaRequest,\n assertValidMfaResponse,\n} from './schemas.js';\nimport type {\n AuthenticationResponseJSON,\n EnrolledCredential,\n MfaCredential,\n MfaCredentialStatus,\n MfaCredentialType,\n MfaEnrollCompleteRequest,\n MfaEnrollRequest,\n MfaVerifyCompleteRequest,\n MfaVerifyRequest,\n PublicKeyCredentialCreationOptionsJSON as PasskeyCreationOptions,\n PublicKeyCredentialRequestOptionsJSON as PasskeyRequestOptions,\n RegistrationResponseJSON,\n} from './types.js';\n\nexport const MFA_ENROLL_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/mfa/enroll`;\n\nexport const MFA_ENROLL_COMPLETE_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/mfa/enroll/complete`;\n\nexport const MFA_VERIFY_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/mfa/verify`;\n\nexport const MFA_VERIFY_COMPLETE_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/mfa/verify/complete`;\n\nexport const MFA_CREDENTIALS_URL = (env: Env): string =>\n `${getEnvUrls(env).authApiUrl}/api/v2/mfa/credentials`;\n\ntype EnrollmentServiceResult = {\n flowId: string;\n expiresAt: number;\n publicKey?: PasskeyCreationOptions;\n};\n\ntype VerificationServiceResult = {\n flowId: string;\n expiresAt: number;\n publicKey?: PasskeyRequestOptions;\n};\n\nexport type MfaStepUpAssertion = {\n /** AAL2 assertion JWT to exchange at Hydra for an elevated access token. */\n token: string;\n /** Assertion lifetime in seconds. */\n expiresIn: number;\n};\n\ntype EnrollmentCompletionParams = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n credential_type: MfaCredentialType;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n flow_id: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n otp_code?: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n passkey_attestation?: RegistrationResponseJSON;\n};\n\ntype VerificationCompletionParams = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n credential_type: MfaCredentialType;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n flow_id: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n otp_code?: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n passkey_assertion?: AuthenticationResponseJSON;\n};\n\n/**\n * Reads a credential's enrollment date. Unlike flow deadlines, this is display\n * metadata, so an unparsable value is dropped instead of rejecting the whole\n * credential list.\n *\n * @param value - The raw `enrolled_at` value, if the server sent one.\n * @returns The epoch milliseconds, or undefined when absent or unparsable.\n */\nfunction parseEnrolledAt(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n const enrolledAt = Date.parse(value);\n if (Number.isNaN(enrolledAt)) {\n log.warn(`Ignoring unparsable MFA credential enrolled_at: ${value}`);\n return undefined;\n }\n return enrolledAt;\n}\n\nfunction parseExpiresAt(value: string): number {\n const expiresAt = Date.parse(value);\n if (Number.isNaN(expiresAt)) {\n throw new MfaError('invalid_response', `Invalid expires_at: ${value}`);\n }\n return expiresAt;\n}\n\n/**\n * Parses passkey creation data embedded in an enrollment response.\n *\n * @param value - JSON-encoded creation options.\n * @returns Validated public-key creation options.\n */\nexport function parsePasskeyCreateData(value: string): PasskeyCreationOptions {\n try {\n const parsed: unknown = JSON.parse(value);\n assertValidMfaResponse(parsed, PasskeyCreateDataStruct);\n return parsed.publicKey;\n } catch (error) {\n if (error instanceof MfaError) {\n throw error;\n }\n const message = toErrorMessage(error);\n throw new MfaError('invalid_response', message);\n }\n}\n\n/**\n * Parses passkey request data embedded in a verification response.\n *\n * @param value - JSON-encoded request options.\n * @returns Validated public-key request options.\n */\nexport function parsePasskeyRequestData(value: string): PasskeyRequestOptions {\n try {\n const parsed: unknown = JSON.parse(value);\n assertValidMfaResponse(parsed, PasskeyRequestDataStruct);\n return parsed.publicKey;\n } catch (error) {\n if (error instanceof MfaError) {\n throw error;\n }\n const message = toErrorMessage(error);\n throw new MfaError('invalid_response', message);\n }\n}\n\n/**\n * Reads a `Retry-After` header as a delay. The human-readable error message is\n * deliberately not parsed: the API documents it as unstable.\n *\n * @param response - The throttled response.\n * @returns The delay in milliseconds, or undefined without a usable header.\n */\nfunction parseRetryAfter(response: Response): number | undefined {\n const header = response.headers.get('Retry-After');\n if (!header) {\n return undefined;\n }\n const seconds = Number(header);\n if (Number.isInteger(seconds)) {\n return Math.max(0, seconds * 1000);\n }\n const date = Date.parse(header);\n return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());\n}\n\n/**\n * Reads and validates the JSON error body of a failed MFA request.\n *\n * When the body parses as JSON but does not match the documented error\n * shape, a `message` field is salvaged if present so callers still get a\n * useful diagnostic instead of a content-free fallback.\n *\n * @param response - The failed response.\n * @returns The validated error body, a best-effort salvage of it, or\n * undefined when the body could not be parsed as JSON at all.\n */\nasync function readErrorBody(\n response: Response,\n): Promise<{ code?: string; message: string } | undefined> {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n return undefined;\n }\n\n try {\n assertValidMfaResponse(body, MfaErrorResponseStruct);\n return body;\n } catch {\n const message = asRecord(body)?.message;\n return typeof message === 'string' ? { message } : undefined;\n }\n}\n\nasync function throwMfaError(\n response: Response,\n errorPrefix: string,\n): Promise<never> {\n const { status } = response;\n const body = await readErrorBody(response);\n const message = `${errorPrefix}: ${body?.message ?? `HTTP ${status}`}`;\n\n // Status-only classification first: gateways and load balancers answer\n // 401/429/502 without the service's JSON body, and the caller still needs\n // to invalidate its session, honour Retry-After, or back off.\n if (status === HTTP_STATUS_CODES.UNAUTHORIZED) {\n throw new MfaError('authentication_required', message, { status });\n }\n\n const code = body?.code;\n switch (code) {\n case 'credential_already_enrolled':\n case 'email_already_enrolled':\n throw new CredentialAlreadyEnrolledError(code, message, status);\n case 'credential_not_enrolled':\n throw new CredentialNotEnrolledError(message, status);\n case 'flow_expired':\n case 'invalid_flow':\n throw new MfaFlowExpiredError(code, message, status);\n case 'mfa_identity_missing':\n throw new MfaIdentityMissingError(message, status);\n case 'invalid_code':\n case 'invalid_attestation':\n case 'invalid_assertion':\n throw new MfaVerificationFailedError(code, message, status);\n case 'too_many_attempts':\n throw new TooManyAttemptsError(message, status);\n case 'max_passkeys_reached':\n throw new MaxPasskeysReachedError(message, status);\n case 'max_identifiers_reached':\n throw new MaxIdentifiersReachedError(message, status);\n case 'otp_resend_cooldown':\n throw new OtpResendCooldownError(\n message,\n parseRetryAfter(response),\n status,\n );\n case 'kratos_unavailable':\n throw new MfaUnavailableError(message, status);\n default:\n break;\n }\n\n if (status === HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {\n throw new MfaRateLimitedError(message, parseRetryAfter(response), status);\n }\n if (status === HTTP_STATUS_CODES.BAD_GATEWAY) {\n throw new MfaUnavailableError(message, status);\n }\n if (!body) {\n throw new MfaError(\n 'invalid_response',\n `${errorPrefix}: Unexpected error response (HTTP ${status})`,\n { status },\n );\n }\n throw new MfaError(code ?? 'server_error', message, { status });\n}\n\nasync function requestJson(\n url: string,\n accessToken: string,\n init?: { method?: 'GET' | 'POST'; body?: Json },\n): Promise<Json> {\n let response: Response;\n try {\n response = await fetch(url, {\n method: init?.method ?? 'GET',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n ...(init?.body === undefined\n ? {}\n : { 'Content-Type': 'application/json' }),\n },\n ...(init?.body === undefined ? {} : { body: JSON.stringify(init.body) }),\n });\n } catch (error) {\n const message = toErrorMessage(error);\n throw new MfaUnavailableError(`MFA request failed: ${message}`);\n }\n\n if (!response.ok) {\n return await throwMfaError(response, 'MFA request failed');\n }\n\n try {\n return await response.json();\n } catch (error) {\n const message = toErrorMessage(error);\n throw new MfaError('invalid_response', message, {\n status: response.status,\n });\n }\n}\n\n/**\n * Begins enrollment of an MFA credential.\n *\n * @param env - Authentication environment.\n * @param accessToken - Primary profile access token.\n * @param body - Enrollment request.\n * @returns Validated enrollment flow data.\n */\nexport async function mfaEnroll(\n env: Env,\n accessToken: string,\n body: MfaEnrollRequest,\n): Promise<EnrollmentServiceResult> {\n const json = await requestJson(MFA_ENROLL_URL(env), accessToken, {\n method: 'POST',\n body,\n });\n assertValidMfaResponse(json, MfaEnrollResponseStruct);\n\n return {\n flowId: json.flow_id,\n expiresAt: parseExpiresAt(json.expires_at),\n ...(json.passkey_create_data\n ? { publicKey: parsePasskeyCreateData(json.passkey_create_data) }\n : {}),\n };\n}\n\n/**\n * Completes enrollment of an MFA credential.\n *\n * @param env - Authentication environment.\n * @param accessToken - Primary profile access token.\n * @param params - Flow identifier and enrollment proof.\n */\nexport async function mfaEnrollComplete(\n env: Env,\n accessToken: string,\n params: EnrollmentCompletionParams,\n): Promise<void> {\n let body: MfaEnrollCompleteRequest = {\n credential_type: params.credential_type,\n flow_id: params.flow_id,\n ...(params.otp_code ? { otp_code: params.otp_code } : {}),\n };\n if (params.passkey_attestation) {\n assertValidMfaRequest(\n params.passkey_attestation,\n RegistrationResponseJSONStruct,\n );\n body = {\n ...body,\n passkey_attestation: JSON.stringify(params.passkey_attestation),\n };\n }\n\n const json = await requestJson(MFA_ENROLL_COMPLETE_URL(env), accessToken, {\n method: 'POST',\n body,\n });\n assertValidMfaResponse(json, MfaEnrollCompleteResponseStruct);\n}\n\n/**\n * Begins step-up verification with an enrolled credential.\n *\n * @param env - Authentication environment.\n * @param accessToken - Primary profile access token.\n * @param body - Verification request.\n * @returns Validated verification flow data.\n */\nexport async function mfaVerify(\n env: Env,\n accessToken: string,\n body: MfaVerifyRequest,\n): Promise<VerificationServiceResult> {\n const json = await requestJson(MFA_VERIFY_URL(env), accessToken, {\n method: 'POST',\n body,\n });\n assertValidMfaResponse(json, MfaVerifyResponseStruct);\n\n return {\n flowId: json.flow_id,\n expiresAt: parseExpiresAt(json.expires_at),\n ...(json.passkey_request_data\n ? { publicKey: parsePasskeyRequestData(json.passkey_request_data) }\n : {}),\n };\n}\n\n/**\n * Completes step-up verification with an enrolled credential.\n *\n * @param env - Authentication environment.\n * @param accessToken - Primary profile access token.\n * @param params - Flow identifier and verification proof.\n * @returns The AAL2 assertion JWT and its lifetime in seconds.\n */\nexport async function mfaVerifyComplete(\n env: Env,\n accessToken: string,\n params: VerificationCompletionParams,\n): Promise<MfaStepUpAssertion> {\n let body: MfaVerifyCompleteRequest = {\n credential_type: params.credential_type,\n flow_id: params.flow_id,\n ...(params.otp_code ? { otp_code: params.otp_code } : {}),\n };\n if (params.passkey_assertion) {\n assertValidMfaRequest(\n params.passkey_assertion,\n AuthenticationResponseJSONStruct,\n );\n body = {\n ...body,\n passkey_assertion: JSON.stringify(params.passkey_assertion),\n };\n }\n\n const json = await requestJson(MFA_VERIFY_COMPLETE_URL(env), accessToken, {\n method: 'POST',\n body,\n });\n assertValidMfaResponse(json, MfaVerifyCompleteResponseStruct);\n return { token: json.token, expiresIn: json.expires_in };\n}\n\nfunction isSupportedStatus(status: string): status is MfaCredentialStatus {\n return status === 'active' || status === 'pending';\n}\n\n/**\n * Maps a server credential to its public controller representation.\n *\n * Unknown credential types or statuses are dropped so the server can extend\n * either without invalidating the whole list.\n *\n * @param credential - Validated server credential.\n * @returns A supported credential, or null when it cannot be represented.\n */\nexport function toEnrolledCredential(\n credential: MfaCredential,\n): EnrolledCredential | null {\n const { credential_type: type, status } = credential;\n if (!isSupportedStatus(status)) {\n log.warn(`Ignoring MFA credential with unsupported status: ${status}`);\n return null;\n }\n\n const enrolledAt = parseEnrolledAt(credential.enrolled_at);\n const base = {\n status,\n ...(enrolledAt === undefined ? {} : { enrolledAt }),\n };\n\n if (type === 'passkey') {\n return {\n type,\n ...base,\n ...(credential.passkey?.display_name\n ? { displayName: credential.passkey.display_name }\n : {}),\n };\n }\n\n if (type === 'email_otp' && credential.email?.address !== undefined) {\n return {\n type,\n ...base,\n email: credential.email.address,\n // The spec marks `verified` optional; an active row is verified.\n verified: credential.email.verified ?? status === 'active',\n };\n }\n\n log.warn(`Ignoring unsupported or incomplete MFA credential: ${type}`);\n return null;\n}\n\n/**\n * Gets the credentials enrolled on the canonical profile.\n *\n * @param env - Authentication environment.\n * @param accessToken - Primary profile access token.\n * @returns Supported enrolled credentials.\n */\nexport async function getMfaCredentials(\n env: Env,\n accessToken: string,\n): Promise<EnrolledCredential[]> {\n const json = await requestJson(MFA_CREDENTIALS_URL(env), accessToken);\n assertValidMfaResponse(json, MfaCredentialsResponseStruct);\n return json.credentials\n .map(toEnrolledCredential)\n .filter((credential): credential is EnrolledCredential =>\n Boolean(credential),\n );\n}\n"]}
@@ -1,125 +0,0 @@
1
- import type { Infer } from '@metamask/superstruct';
2
- import type { AuthenticationResponseJSONStruct, MfaCredentialStruct, MfaCredentialsResponseStruct, MfaEmailDetailStruct, MfaEnrollCompleteResponseStruct, MfaEnrollResponseStruct, MfaPasskeyDetailStruct, MfaVerifyCompleteResponseStruct, MfaVerifyResponseStruct, PublicKeyCredentialCreationOptionsJSONStruct, PublicKeyCredentialRequestOptionsJSONStruct, RegistrationResponseJSONStruct } from './schemas.js';
3
- import { MFA_CREDENTIAL_TYPES } from './schemas.js';
4
- export { MFA_CREDENTIAL_TYPES };
5
- export type MfaCredentialType = (typeof MFA_CREDENTIAL_TYPES)[number];
6
- export type MfaCredentialStatus = 'active' | 'pending';
7
- export type PublicKeyCredentialCreationOptionsJSON = Infer<typeof PublicKeyCredentialCreationOptionsJSONStruct>;
8
- export type PublicKeyCredentialRequestOptionsJSON = Infer<typeof PublicKeyCredentialRequestOptionsJSONStruct>;
9
- export type RegistrationResponseJSON = Infer<typeof RegistrationResponseJSONStruct>;
10
- export type AuthenticationResponseJSON = Infer<typeof AuthenticationResponseJSONStruct>;
11
- export type MfaEnrollResponse = Infer<typeof MfaEnrollResponseStruct>;
12
- export type MfaEnrollCompleteResponse = Infer<typeof MfaEnrollCompleteResponseStruct>;
13
- export type MfaVerifyResponse = Infer<typeof MfaVerifyResponseStruct>;
14
- export type MfaVerifyCompleteResponse = Infer<typeof MfaVerifyCompleteResponseStruct>;
15
- export type MfaCredentialsResponse = Infer<typeof MfaCredentialsResponseStruct>;
16
- export type MfaCredential = Infer<typeof MfaCredentialStruct>;
17
- export type MfaPasskeyDetail = Infer<typeof MfaPasskeyDetailStruct>;
18
- export type MfaEmailDetail = Infer<typeof MfaEmailDetailStruct>;
19
- export type MfaEnrollRequest = {
20
- credential_type: MfaCredentialType;
21
- identifier?: string;
22
- };
23
- export type MfaEnrollCompleteRequest = {
24
- credential_type: MfaCredentialType;
25
- flow_id: string;
26
- otp_code?: string;
27
- passkey_attestation?: string;
28
- };
29
- export type MfaVerifyRequest = {
30
- credential_type: MfaCredentialType;
31
- };
32
- export type MfaVerifyCompleteRequest = {
33
- credential_type: MfaCredentialType;
34
- flow_id: string;
35
- passkey_assertion?: string;
36
- otp_code?: string;
37
- };
38
- export type EnrolledCredential = {
39
- type: 'passkey';
40
- status: MfaCredentialStatus;
41
- enrolledAt?: number;
42
- displayName?: string;
43
- } | {
44
- type: 'email_otp';
45
- status: MfaCredentialStatus;
46
- enrolledAt?: number;
47
- email: string;
48
- verified: boolean;
49
- };
50
- /**
51
- * Caller-supplied context attached to MFA trace spans. `operation` names the
52
- * client flow that needs the credential (for example `money.signTransaction`).
53
- */
54
- export type TokenReason = {
55
- operation: string;
56
- };
57
- export type EnrollmentChallenge = {
58
- type: 'passkey';
59
- flowId: string;
60
- expiresAt: number;
61
- publicKey: PublicKeyCredentialCreationOptionsJSON;
62
- } | {
63
- type: 'email_otp';
64
- flowId: string;
65
- expiresAt: number;
66
- };
67
- export type EnrollmentProof = {
68
- type: 'passkey';
69
- attestation: RegistrationResponseJSON;
70
- } | {
71
- type: 'email_otp';
72
- code: string;
73
- };
74
- export type StepUpChallenge = {
75
- type: 'passkey';
76
- flowId: string;
77
- expiresAt: number;
78
- publicKey: PublicKeyCredentialRequestOptionsJSON;
79
- } | {
80
- type: 'email_otp';
81
- flowId: string;
82
- expiresAt: number;
83
- };
84
- export type StepUpProof = {
85
- type: 'passkey';
86
- assertion: AuthenticationResponseJSON;
87
- } | {
88
- type: 'email_otp';
89
- code: string;
90
- };
91
- export type ElevatedProfileToken = {
92
- accessToken: string;
93
- expiresIn: number;
94
- obtainedAt: number;
95
- claims: {
96
- sub: string;
97
- aal: 2;
98
- amr: MfaCredentialType[];
99
- exp: number;
100
- };
101
- };
102
- export type BeginEnrollmentRequest = {
103
- type: MfaCredentialType;
104
- email?: string;
105
- reason: TokenReason;
106
- };
107
- export type CompleteEnrollmentRequest = {
108
- flowId: string;
109
- proof: EnrollmentProof;
110
- reason: TokenReason;
111
- };
112
- export type BeginStepUpRequest = {
113
- type: MfaCredentialType;
114
- reason: TokenReason;
115
- };
116
- export type CompleteStepUpRequest = {
117
- flowId: string;
118
- proof: StepUpProof;
119
- reason: TokenReason;
120
- };
121
- export type GetElevatedTokenRequest = {
122
- maxSessionAgeMs?: number;
123
- };
124
- export type MfaErrorCode = 'max_passkeys_reached' | 'max_identifiers_reached' | 'email_already_enrolled' | 'credential_already_enrolled' | 'credential_not_enrolled' | 'mfa_identity_missing' | 'otp_resend_cooldown' | 'rate_limited' | 'kratos_unavailable' | 'flow_expired' | 'invalid_flow' | 'invalid_attestation' | 'invalid_code' | 'invalid_assertion' | 'too_many_attempts' | 'elevated_token_invalid' | 'authentication_required' | 'server_error' | 'invalid_response' | 'invalid_request';
125
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/sdk/authentication-jwt-bearer/mfa/types.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import { MFA_CREDENTIAL_TYPES } from './schemas.js';
2
- export { MFA_CREDENTIAL_TYPES };
3
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/sdk/authentication-jwt-bearer/mfa/types.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,oBAAoB,EAAE,CAAC","sourcesContent":["import type { Infer } from '@metamask/superstruct';\n\nimport type {\n AuthenticationResponseJSONStruct,\n MfaCredentialStruct,\n MfaCredentialsResponseStruct,\n MfaEmailDetailStruct,\n MfaEnrollCompleteResponseStruct,\n MfaEnrollResponseStruct,\n MfaPasskeyDetailStruct,\n MfaVerifyCompleteResponseStruct,\n MfaVerifyResponseStruct,\n PublicKeyCredentialCreationOptionsJSONStruct,\n PublicKeyCredentialRequestOptionsJSONStruct,\n RegistrationResponseJSONStruct,\n} from './schemas.js';\nimport { MFA_CREDENTIAL_TYPES } from './schemas.js';\n\nexport { MFA_CREDENTIAL_TYPES };\n\nexport type MfaCredentialType = (typeof MFA_CREDENTIAL_TYPES)[number];\n\nexport type MfaCredentialStatus = 'active' | 'pending';\n\nexport type PublicKeyCredentialCreationOptionsJSON = Infer<\n typeof PublicKeyCredentialCreationOptionsJSONStruct\n>;\n\nexport type PublicKeyCredentialRequestOptionsJSON = Infer<\n typeof PublicKeyCredentialRequestOptionsJSONStruct\n>;\n\nexport type RegistrationResponseJSON = Infer<\n typeof RegistrationResponseJSONStruct\n>;\n\nexport type AuthenticationResponseJSON = Infer<\n typeof AuthenticationResponseJSONStruct\n>;\n\nexport type MfaEnrollResponse = Infer<typeof MfaEnrollResponseStruct>;\n\nexport type MfaEnrollCompleteResponse = Infer<\n typeof MfaEnrollCompleteResponseStruct\n>;\n\nexport type MfaVerifyResponse = Infer<typeof MfaVerifyResponseStruct>;\n\nexport type MfaVerifyCompleteResponse = Infer<\n typeof MfaVerifyCompleteResponseStruct\n>;\n\nexport type MfaCredentialsResponse = Infer<typeof MfaCredentialsResponseStruct>;\n\nexport type MfaCredential = Infer<typeof MfaCredentialStruct>;\n\nexport type MfaPasskeyDetail = Infer<typeof MfaPasskeyDetailStruct>;\n\nexport type MfaEmailDetail = Infer<typeof MfaEmailDetailStruct>;\n\nexport type MfaEnrollRequest = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n credential_type: MfaCredentialType;\n identifier?: string;\n};\n\nexport type MfaEnrollCompleteRequest = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n credential_type: MfaCredentialType;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n flow_id: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n otp_code?: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n passkey_attestation?: string;\n};\n\nexport type MfaVerifyRequest = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n credential_type: MfaCredentialType;\n};\n\nexport type MfaVerifyCompleteRequest = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n credential_type: MfaCredentialType;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n flow_id: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n passkey_assertion?: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n otp_code?: string;\n};\n\nexport type EnrolledCredential =\n | {\n type: 'passkey';\n status: MfaCredentialStatus;\n enrolledAt?: number;\n displayName?: string;\n }\n | {\n type: 'email_otp';\n status: MfaCredentialStatus;\n enrolledAt?: number;\n email: string;\n verified: boolean;\n };\n\n/**\n * Caller-supplied context attached to MFA trace spans. `operation` names the\n * client flow that needs the credential (for example `money.signTransaction`).\n */\nexport type TokenReason = {\n operation: string;\n};\n\nexport type EnrollmentChallenge =\n | {\n type: 'passkey';\n flowId: string;\n expiresAt: number;\n publicKey: PublicKeyCredentialCreationOptionsJSON;\n }\n | {\n type: 'email_otp';\n flowId: string;\n expiresAt: number;\n };\n\nexport type EnrollmentProof =\n | {\n type: 'passkey';\n attestation: RegistrationResponseJSON;\n }\n | {\n type: 'email_otp';\n code: string;\n };\n\nexport type StepUpChallenge =\n | {\n type: 'passkey';\n flowId: string;\n expiresAt: number;\n publicKey: PublicKeyCredentialRequestOptionsJSON;\n }\n | {\n type: 'email_otp';\n flowId: string;\n expiresAt: number;\n };\n\nexport type StepUpProof =\n | {\n type: 'passkey';\n assertion: AuthenticationResponseJSON;\n }\n | {\n type: 'email_otp';\n code: string;\n };\n\nexport type ElevatedProfileToken = {\n accessToken: string;\n expiresIn: number;\n obtainedAt: number;\n claims: {\n sub: string;\n aal: 2;\n amr: MfaCredentialType[];\n exp: number;\n };\n};\n\nexport type BeginEnrollmentRequest = {\n type: MfaCredentialType;\n email?: string;\n reason: TokenReason;\n};\n\nexport type CompleteEnrollmentRequest = {\n flowId: string;\n proof: EnrollmentProof;\n reason: TokenReason;\n};\n\nexport type BeginStepUpRequest = {\n type: MfaCredentialType;\n reason: TokenReason;\n};\n\nexport type CompleteStepUpRequest = {\n flowId: string;\n proof: StepUpProof;\n reason: TokenReason;\n};\n\nexport type GetElevatedTokenRequest = {\n maxSessionAgeMs?: number;\n};\n\nexport type MfaErrorCode =\n | 'max_passkeys_reached'\n | 'max_identifiers_reached'\n | 'email_already_enrolled'\n | 'credential_already_enrolled'\n | 'credential_not_enrolled'\n | 'mfa_identity_missing'\n | 'otp_resend_cooldown'\n | 'rate_limited'\n | 'kratos_unavailable'\n | 'flow_expired'\n | 'invalid_flow'\n | 'invalid_attestation'\n | 'invalid_code'\n | 'invalid_assertion'\n | 'too_many_attempts'\n | 'elevated_token_invalid'\n | 'authentication_required'\n | 'server_error'\n | 'invalid_response'\n | 'invalid_request';\n"]}
@@ -1,10 +0,0 @@
1
- /**
2
- * Narrows an unknown value to a plain record, for reading optional fields off
3
- * untrusted data (parsed JSON, decoded JWT payloads) before it has been
4
- * validated against a struct.
5
- *
6
- * @param value - The value to narrow.
7
- * @returns The value as a record, or undefined if it is not an object.
8
- */
9
- export declare function asRecord(value: unknown): Record<string, unknown> | undefined;
10
- //# sourceMappingURL=as-record.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"as-record.d.ts","sourceRoot":"","sources":["../../../src/sdk/utils/as-record.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAI5E"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Narrows an unknown value to a plain record, for reading optional fields off
3
- * untrusted data (parsed JSON, decoded JWT payloads) before it has been
4
- * validated against a struct.
5
- *
6
- * @param value - The value to narrow.
7
- * @returns The value as a record, or undefined if it is not an object.
8
- */
9
- export function asRecord(value) {
10
- return typeof value === 'object' && value !== null
11
- ? value
12
- : undefined;
13
- }
14
- //# sourceMappingURL=as-record.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"as-record.js","sourceRoot":"","sources":["../../../src/sdk/utils/as-record.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAChD,CAAC,CAAE,KAAiC;QACpC,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC","sourcesContent":["/**\n * Narrows an unknown value to a plain record, for reading optional fields off\n * untrusted data (parsed JSON, decoded JWT payloads) before it has been\n * validated against a struct.\n *\n * @param value - The value to narrow.\n * @returns The value as a record, or undefined if it is not an object.\n */\nexport function asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n"]}
@@ -1,13 +0,0 @@
1
- /**
2
- * Decodes a JWT payload without verifying its signature.
3
- *
4
- * Use this only for inspecting claims on a token received from a trusted
5
- * exchange. Signature verification remains the authorization server's
6
- * responsibility.
7
- *
8
- * @param token - JWT to decode.
9
- * @returns The parsed payload.
10
- * @throws If the token or payload is malformed.
11
- */
12
- export declare function decodeJwtPayload(token: string): unknown;
13
- //# sourceMappingURL=jwt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../src/sdk/utils/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CASvD"}
@@ -1,21 +0,0 @@
1
- /**
2
- * Decodes a JWT payload without verifying its signature.
3
- *
4
- * Use this only for inspecting claims on a token received from a trusted
5
- * exchange. Signature verification remains the authorization server's
6
- * responsibility.
7
- *
8
- * @param token - JWT to decode.
9
- * @returns The parsed payload.
10
- * @throws If the token or payload is malformed.
11
- */
12
- export function decodeJwtPayload(token) {
13
- const parts = token.split('.');
14
- if (parts.length !== 3 || !parts[1]) {
15
- throw new Error('Invalid JWT');
16
- }
17
- const base64 = parts[1].replace(/-/gu, '+').replace(/_/gu, '/');
18
- const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, '=');
19
- return JSON.parse(atob(padded));
20
- }
21
- //# sourceMappingURL=jwt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../../src/sdk/utils/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAClC,CAAC","sourcesContent":["/**\n * Decodes a JWT payload without verifying its signature.\n *\n * Use this only for inspecting claims on a token received from a trusted\n * exchange. Signature verification remains the authorization server's\n * responsibility.\n *\n * @param token - JWT to decode.\n * @returns The parsed payload.\n * @throws If the token or payload is malformed.\n */\nexport function decodeJwtPayload(token: string): unknown {\n const parts = token.split('.');\n if (parts.length !== 3 || !parts[1]) {\n throw new Error('Invalid JWT');\n }\n\n const base64 = parts[1].replace(/-/gu, '+').replace(/_/gu, '/');\n const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, '=');\n return JSON.parse(atob(padded));\n}\n"]}