@finueva/auth 0.18.1 → 0.20.0

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.
package/dist/device.js CHANGED
@@ -178,6 +178,11 @@ const messages = {
178
178
  invalid_credentials: "The credentials are invalid.",
179
179
  invalid_auth_input: "The authentication input is invalid.",
180
180
  account_conflict: "The account is not available.",
181
+ google_recovery_in_progress: "A Google connection is already being completed. Return to that sign-in, or wait up to ten minutes and restart.",
182
+ google_recovery_not_required: "Google account recovery is not required.",
183
+ google_recovery_invalid: "The Google account recovery request is invalid.",
184
+ google_recovery_expired: "Google account recovery has expired. Start Google sign-in again.",
185
+ google_recovery_account_mismatch: "Sign in to the existing account associated with this Google identity.",
181
186
  password_reset_invalid: "The password reset request is invalid.",
182
187
  authentication_required: "Authentication is required.",
183
188
  request_origin_denied: "The request origin is not allowed.",
@@ -198,7 +203,18 @@ const messages = {
198
203
  platform_target_unavailable: "The platform administration target is unavailable.",
199
204
  platform_quorum_unavailable: "Platform administration quorum is unavailable.",
200
205
  platform_recovery_required: "Platform administration requires separate recovery.",
201
- identity_authority_unavailable: "Authentication is temporarily unavailable."
206
+ identity_authority_unavailable: "Authentication is temporarily unavailable.",
207
+ two_factor_required: "A second authentication factor is required.",
208
+ two_factor_code_invalid: "The verification code is invalid.",
209
+ two_factor_challenge_expired: "The second-factor challenge has ended. Sign in again.",
210
+ two_factor_locked: "Second-factor verification is temporarily locked.",
211
+ recent_sign_in_required: "A recent sign-in is required.",
212
+ enterprise_recovery_required: "Enterprise administration evidence requires operator recovery.",
213
+ recent_authentication_required: "A ready recent-authentication action is required.",
214
+ organization_closure_confirmation_mismatch: "The confirmation does not match the organization.",
215
+ organization_closure_cancellation_ended: "The closure cancellation period has ended.",
216
+ ceremony_return_refused: "The return address is not registered for this application.",
217
+ password_sign_in_required: "A password sign-in method is required for this passkey change."
202
218
  };
203
219
  var AuthError = class extends Error {
204
220
  code;
@@ -327,7 +343,7 @@ function normalizeIdInput(value) {
327
343
  return value;
328
344
  }
329
345
  function normalizeOrganization(value) {
330
- exact(value, [
346
+ exact$2(value, [
331
347
  "capabilities",
332
348
  "id",
333
349
  "lifecycle",
@@ -337,7 +353,7 @@ function normalizeOrganization(value) {
337
353
  "slug"
338
354
  ]);
339
355
  if (!isId(value.id) || !boundedString(value.name, 255) || !boundedString(value.slug, 255) || value.lifecycle !== "ordinary" && value.lifecycle !== "managed" || !role(value.role) || !isObject(value.capabilities)) throw authorityUnavailable();
340
- exact(value.capabilities, [
356
+ exact$2(value.capabilities, [
341
357
  "readInvitations",
342
358
  "readMembers",
343
359
  "readTeams"
@@ -399,7 +415,7 @@ function normalizeOrganizationCreationInput(name, slug, idempotencyKey) {
399
415
  };
400
416
  }
401
417
  function normalizeCreatedOrganization(value) {
402
- exact(value, [
418
+ exact$2(value, [
403
419
  "id",
404
420
  "name",
405
421
  "slug"
@@ -419,7 +435,7 @@ function normalizeOrganizationTeamCreationInput(name, idempotencyKey) {
419
435
  };
420
436
  }
421
437
  function normalizeCreatedOrganizationTeam(value) {
422
- exact(value, ["id", "name"]);
438
+ exact$2(value, ["id", "name"]);
423
439
  if (!isId(value.id) || !boundedString(value.name, 255)) throw authorityUnavailable();
424
440
  return {
425
441
  id: value.id,
@@ -446,7 +462,7 @@ function normalizeOrganizationMemberInvitationCreationInput(value) {
446
462
  };
447
463
  }
448
464
  function normalizeCreatedOrganizationMemberInvitation(value) {
449
- exact(value, ["expiresAt", "id"]);
465
+ exact$2(value, ["expiresAt", "id"]);
450
466
  if (!isId(value.id)) throw authorityUnavailable();
451
467
  return {
452
468
  id: value.id,
@@ -454,7 +470,7 @@ function normalizeCreatedOrganizationMemberInvitation(value) {
454
470
  };
455
471
  }
456
472
  function normalizeOrganizations(value) {
457
- exact(value, ["nextCursor", "organizations"]);
473
+ exact$2(value, ["nextCursor", "organizations"]);
458
474
  if (!Array.isArray(value.organizations) || value.organizations.length > 100) throw authorityUnavailable();
459
475
  return {
460
476
  organizations: unique(value.organizations.map(normalizeOrganization), (item) => item.id),
@@ -462,11 +478,11 @@ function normalizeOrganizations(value) {
462
478
  };
463
479
  }
464
480
  function normalizeOrganizationMembers(value) {
465
- exact(value, ["members", "nextCursor"]);
481
+ exact$2(value, ["members", "nextCursor"]);
466
482
  if (!Array.isArray(value.members) || value.members.length > 100) throw authorityUnavailable();
467
483
  return {
468
484
  members: unique(value.members.map((member) => {
469
- exact(member, [
485
+ exact$2(member, [
470
486
  "email",
471
487
  "id",
472
488
  "image",
@@ -495,11 +511,11 @@ function normalizeOrganizationMembers(value) {
495
511
  };
496
512
  }
497
513
  function normalizeOrganizationTeams(value) {
498
- exact(value, ["nextCursor", "teams"]);
514
+ exact$2(value, ["nextCursor", "teams"]);
499
515
  if (!Array.isArray(value.teams) || value.teams.length > 100) throw authorityUnavailable();
500
516
  return {
501
517
  teams: unique(value.teams.map((team) => {
502
- exact(team, [
518
+ exact$2(team, [
503
519
  "category",
504
520
  "createdAt",
505
521
  "id",
@@ -517,7 +533,7 @@ function normalizeOrganizationTeams(value) {
517
533
  };
518
534
  }
519
535
  function normalizeOrganizationTeamMembers(value) {
520
- exact(value, ["memberIds", "nextCursor"]);
536
+ exact$2(value, ["memberIds", "nextCursor"]);
521
537
  if (!Array.isArray(value.memberIds) || value.memberIds.length > 100) throw authorityUnavailable();
522
538
  return {
523
539
  memberIds: unique(value.memberIds.map((item) => normalizeResponseId(item)), (item) => item),
@@ -525,7 +541,7 @@ function normalizeOrganizationTeamMembers(value) {
525
541
  };
526
542
  }
527
543
  function normalizeOrganizationInvitation(value) {
528
- exact(value, [
544
+ exact$2(value, [
529
545
  "createdAt",
530
546
  "email",
531
547
  "expiresAt",
@@ -536,7 +552,7 @@ function normalizeOrganizationInvitation(value) {
536
552
  "teamIds"
537
553
  ]);
538
554
  if (!isId(value.id) || typeof value.email !== "string" || value.email.length > 320 || !email.test(value.email) || !role(value.role) || value.status !== "pending" || !Array.isArray(value.teamIds) || value.teamIds.length > 100 || !isObject(value.inviter)) throw authorityUnavailable();
539
- exact(value.inviter, ["membershipId", "name"]);
555
+ exact$2(value.inviter, ["membershipId", "name"]);
540
556
  if (!isId(value.inviter.membershipId) || !boundedString(value.inviter.name, 255)) throw authorityUnavailable();
541
557
  return {
542
558
  id: value.id,
@@ -553,7 +569,7 @@ function normalizeOrganizationInvitation(value) {
553
569
  };
554
570
  }
555
571
  function normalizeOrganizationInvitations(value) {
556
- exact(value, ["invitations", "nextCursor"]);
572
+ exact$2(value, ["invitations", "nextCursor"]);
557
573
  if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
558
574
  return {
559
575
  invitations: unique(value.invitations.map(normalizeOrganizationInvitation), (item) => item.id),
@@ -561,7 +577,7 @@ function normalizeOrganizationInvitations(value) {
561
577
  };
562
578
  }
563
579
  function normalizeReceivedInvitation(value) {
564
- exact(value, [
580
+ exact$2(value, [
565
581
  "expiresAt",
566
582
  "id",
567
583
  "inviterName",
@@ -570,7 +586,7 @@ function normalizeReceivedInvitation(value) {
570
586
  "teams"
571
587
  ]);
572
588
  if (!isId(value.id) || !boundedString(value.inviterName, 255) || !role(value.role) || !Array.isArray(value.teams) || value.teams.length > 100 || !isObject(value.organization)) throw authorityUnavailable();
573
- exact(value.organization, [
589
+ exact$2(value.organization, [
574
590
  "id",
575
591
  "logo",
576
592
  "name",
@@ -587,7 +603,7 @@ function normalizeReceivedInvitation(value) {
587
603
  },
588
604
  role: value.role,
589
605
  teams: unique(value.teams.map((team) => {
590
- exact(team, ["id", "name"]);
606
+ exact$2(team, ["id", "name"]);
591
607
  if (!isId(team.id) || !boundedString(team.name, 255)) throw authorityUnavailable();
592
608
  return {
593
609
  id: team.id,
@@ -599,7 +615,7 @@ function normalizeReceivedInvitation(value) {
599
615
  };
600
616
  }
601
617
  function normalizeReceivedInvitations(value) {
602
- exact(value, ["invitations", "nextCursor"]);
618
+ exact$2(value, ["invitations", "nextCursor"]);
603
619
  if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
604
620
  return {
605
621
  invitations: unique(value.invitations.map(normalizeReceivedInvitation), (item) => item.id),
@@ -657,8 +673,35 @@ function fromOrganizationMutationAuthorityError(value, status, retryAfter) {
657
673
  if (status === 403 && code === "REQUEST_ORIGIN_DENIED") return new AuthError("request_origin_denied", 403);
658
674
  return fromOrganizationReadAuthorityError(value, status);
659
675
  }
676
+ function normalizeOrganizationClosureStartInput(value) {
677
+ if (!isObject(value) || Object.keys(value).sort().join(",") !== "confirmationName,idempotencyKey") throw new TypeError("organization closure input is invalid");
678
+ if (!boundedString(value.confirmationName, 255)) throw new TypeError("confirmationName is invalid");
679
+ return {
680
+ confirmationName: value.confirmationName,
681
+ idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey)
682
+ };
683
+ }
684
+ function normalizeOrganizationClosureCancelInput(value) {
685
+ if (!isObject(value) || Object.keys(value).join(",") !== "idempotencyKey") throw new TypeError("organization closure cancellation input is invalid");
686
+ return { idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey) };
687
+ }
688
+ function normalizeOrganizationOwnershipTransferInput(value) {
689
+ if (!isObject(value) || Object.keys(value).sort().join(",") !== "expectedActorAuthorityRevision,expectedOutgoingOwnerAuthorityRevision,expectedSuccessorAuthorityRevision,idempotencyKey,outgoingOwnerMembershipId,outgoingOwnerRole,successorMembershipId") throw new TypeError("organization ownership transfer input is invalid");
690
+ if (!isId(value.outgoingOwnerMembershipId) || !isId(value.successorMembershipId)) throw new TypeError("ownership transfer membership is invalid");
691
+ if (value.outgoingOwnerMembershipId === value.successorMembershipId) throw new TypeError("ownership transfer memberships must differ");
692
+ if (value.outgoingOwnerRole !== "admin" && value.outgoingOwnerRole !== "member") throw new TypeError("outgoingOwnerRole is invalid");
693
+ return {
694
+ outgoingOwnerMembershipId: value.outgoingOwnerMembershipId,
695
+ successorMembershipId: value.successorMembershipId,
696
+ outgoingOwnerRole: value.outgoingOwnerRole,
697
+ expectedActorAuthorityRevision: normalizeAuthorityRevision(value.expectedActorAuthorityRevision, "expectedActorAuthorityRevision"),
698
+ expectedOutgoingOwnerAuthorityRevision: normalizeAuthorityRevision(value.expectedOutgoingOwnerAuthorityRevision, "expectedOutgoingOwnerAuthorityRevision", true),
699
+ expectedSuccessorAuthorityRevision: normalizeAuthorityRevision(value.expectedSuccessorAuthorityRevision, "expectedSuccessorAuthorityRevision", true),
700
+ idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey)
701
+ };
702
+ }
660
703
  function normalizeOrganizationMemberAuthority(value, organizationId, memberId) {
661
- exact(value, [
704
+ exact$2(value, [
662
705
  "organizationId",
663
706
  "actor",
664
707
  "target"
@@ -676,7 +719,7 @@ function normalizeOrganizationMemberAuthority(value, organizationId, memberId) {
676
719
  };
677
720
  }
678
721
  function normalizeOrganizationAuthorityMemberOutcome(value, includesStatus = false) {
679
- exact(value, [
722
+ exact$2(value, [
680
723
  "memberId",
681
724
  "manualRole",
682
725
  "role",
@@ -691,10 +734,18 @@ function normalizeOrganizationAuthorityMemberOutcome(value, includesStatus = fal
691
734
  authorityRevision: normalizeAuthorityResultRevision(value.authorityRevision)
692
735
  };
693
736
  }
737
+ function normalizeAuthorityRevision(value, name, incremented = false) {
738
+ if (!Number.isSafeInteger(value) || value < 0 || value >= Number.MAX_SAFE_INTEGER - (incremented ? 1 : 0)) throw new TypeError(`${name} is invalid`);
739
+ return value;
740
+ }
694
741
  function normalizeAuthorityResultRevision(value) {
695
742
  if (!Number.isSafeInteger(value) || value < 0 || value >= Number.MAX_SAFE_INTEGER) throw authorityUnavailable();
696
743
  return value;
697
744
  }
745
+ function normalizeAuthorityIdempotencyKey(value) {
746
+ if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value)) throw new TypeError("idempotencyKey is invalid");
747
+ return value;
748
+ }
698
749
  function mapError(code, status) {
699
750
  if (code === "authentication_required") return {
700
751
  code,
@@ -769,7 +820,7 @@ function normalizeProfileImage(value) {
769
820
  function isId(value) {
770
821
  return typeof value === "string" && id.test(value);
771
822
  }
772
- function exact(value, keys) {
823
+ function exact$2(value, keys) {
773
824
  if (!isObject(value) || Object.keys(value).sort().join(",") !== [...keys].sort().join(",")) throw authorityUnavailable();
774
825
  }
775
826
  function boundedString(value, maximum) {
@@ -1230,6 +1281,237 @@ async function readJson(response, maximum = MAX_RESPONSE_BYTES) {
1230
1281
  }
1231
1282
  }
1232
1283
  //#endregion
1284
+ //#region src/two-factor.ts
1285
+ function isTwoFactorChallenge(value) {
1286
+ return isObject(value) && value.twoFactorRedirect === true;
1287
+ }
1288
+ function normalizeTwoFactorStatus(value) {
1289
+ if (value === null) throw new AuthError("authentication_required", 401);
1290
+ if (!isObject(value) || !isObject(value.user) || typeof value.user.twoFactorEnabled !== "boolean") throw authorityUnavailable();
1291
+ return { enabled: value.user.twoFactorEnabled };
1292
+ }
1293
+ //#endregion
1294
+ //#region src/sessions.ts
1295
+ const idPattern$1 = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
1296
+ const MAX_SESSIONS = 50;
1297
+ const itemKeys$1 = [
1298
+ "createdAt",
1299
+ "current",
1300
+ "expiresAt",
1301
+ "id",
1302
+ "ipAddress",
1303
+ "updatedAt",
1304
+ "userAgent"
1305
+ ];
1306
+ function exact$1(value, keys) {
1307
+ return isObject(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
1308
+ }
1309
+ function date$1(value) {
1310
+ if (typeof value !== "string") throw authorityUnavailable();
1311
+ const parsed = new Date(value);
1312
+ if (!Number.isFinite(parsed.getTime()) || parsed.toISOString() !== value) throw authorityUnavailable();
1313
+ return parsed;
1314
+ }
1315
+ function text(value, maximum) {
1316
+ if (value === null) return null;
1317
+ if (typeof value !== "string" || value.length === 0 || value.length > maximum || /[^\x20-\x7e]/.test(value)) throw authorityUnavailable();
1318
+ return value;
1319
+ }
1320
+ function normalizeSessionId(value) {
1321
+ if (typeof value !== "string" || !idPattern$1.test(value)) throw new TypeError("sessionId is invalid");
1322
+ return value;
1323
+ }
1324
+ function normalizeSessionSummary(value) {
1325
+ if (!exact$1(value, itemKeys$1) || typeof value.id !== "string" || !idPattern$1.test(value.id)) throw authorityUnavailable();
1326
+ if (typeof value.current !== "boolean") throw authorityUnavailable();
1327
+ return {
1328
+ id: value.id,
1329
+ current: value.current,
1330
+ createdAt: date$1(value.createdAt),
1331
+ updatedAt: date$1(value.updatedAt),
1332
+ expiresAt: date$1(value.expiresAt),
1333
+ userAgent: text(value.userAgent, 512),
1334
+ ipAddress: text(value.ipAddress, 64)
1335
+ };
1336
+ }
1337
+ function normalizeSessionInventory(value) {
1338
+ if (!exact$1(value, ["sessions", "truncated"]) || !Array.isArray(value.sessions) || value.sessions.length > MAX_SESSIONS || typeof value.truncated !== "boolean") throw authorityUnavailable();
1339
+ const sessions = value.sessions.map(normalizeSessionSummary);
1340
+ if (new Set(sessions.map((session) => session.id)).size !== sessions.length) throw authorityUnavailable();
1341
+ if (sessions.filter((session) => session.current).length !== 1) throw authorityUnavailable();
1342
+ return {
1343
+ sessions,
1344
+ truncated: value.truncated
1345
+ };
1346
+ }
1347
+ function normalizeSessionRevocation(value) {
1348
+ if (!exact$1(value, ["status"]) || value.status !== "revoked") throw authorityUnavailable();
1349
+ }
1350
+ function normalizeOtherSessionRevocation(value) {
1351
+ if (!exact$1(value, ["revoked"]) || !Number.isSafeInteger(value.revoked) || value.revoked < 0) throw authorityUnavailable();
1352
+ return { revoked: value.revoked };
1353
+ }
1354
+ function fromSessionInventoryError(_value, status, retryAfter) {
1355
+ if (status === 400) return new AuthError("invalid_request", 400);
1356
+ if (status === 401) return new AuthError("authentication_required", 401);
1357
+ if (status === 403) return new AuthError("request_origin_denied", 403);
1358
+ if (status === 404 || status === 409) return new AuthError("state_conflict", 409);
1359
+ if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
1360
+ return authorityUnavailable();
1361
+ }
1362
+ //#endregion
1363
+ //#region src/passkeys.ts
1364
+ const idPattern = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
1365
+ const MAX_PASSKEYS = 50;
1366
+ const MAX_RETURN_BYTES = 2048;
1367
+ const PASSKEY_NAME_MAX_LENGTH = 64;
1368
+ const itemKeys = [
1369
+ "backedUp",
1370
+ "createdAt",
1371
+ "deviceType",
1372
+ "id",
1373
+ "name"
1374
+ ];
1375
+ function exact(value, keys) {
1376
+ return isObject(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
1377
+ }
1378
+ function date(value) {
1379
+ if (typeof value !== "string") throw authorityUnavailable();
1380
+ const parsed = new Date(value);
1381
+ if (!Number.isFinite(parsed.getTime()) || parsed.toISOString() !== value) throw authorityUnavailable();
1382
+ return parsed;
1383
+ }
1384
+ function returnInput(value) {
1385
+ if (!isObject(value)) throw new TypeError("ceremony input is invalid");
1386
+ const { applicationId, returnTo } = value;
1387
+ if (typeof applicationId !== "string" || !idPattern.test(applicationId)) throw new TypeError("applicationId is invalid");
1388
+ if (typeof returnTo !== "string" || new TextEncoder().encode(returnTo).byteLength > MAX_RETURN_BYTES || !URL.canParse(returnTo) || new URL(returnTo).toString() !== returnTo) throw new TypeError("returnTo is invalid");
1389
+ return {
1390
+ applicationId,
1391
+ returnTo
1392
+ };
1393
+ }
1394
+ function normalizeCeremonyHandoffInput(value) {
1395
+ const base = returnInput(value);
1396
+ const input = value;
1397
+ switch (input.purpose) {
1398
+ case "passkey_enrollment": return {
1399
+ purpose: input.purpose,
1400
+ ...base
1401
+ };
1402
+ case "passkey_removal": return {
1403
+ purpose: input.purpose,
1404
+ ...base,
1405
+ passkeyId: normalizePasskeyId(input.passkeyId)
1406
+ };
1407
+ case "recent_authentication": {
1408
+ const request = input.request;
1409
+ if (!isObject(request)) throw new TypeError("request is invalid");
1410
+ const organizationId = normalizeIdInput(request.organizationId);
1411
+ if (request.action === "organization_ownership_transfer") {
1412
+ const { action: _action, organizationId: _organizationId, ...transfer } = request;
1413
+ return {
1414
+ purpose: input.purpose,
1415
+ ...base,
1416
+ request: {
1417
+ action: request.action,
1418
+ organizationId,
1419
+ ...normalizeOrganizationOwnershipTransferInput(transfer)
1420
+ }
1421
+ };
1422
+ }
1423
+ if (request.action === "organization_closure_start") {
1424
+ const { action: _action, organizationId: _organizationId, ...closure } = request;
1425
+ return {
1426
+ purpose: input.purpose,
1427
+ ...base,
1428
+ request: {
1429
+ action: request.action,
1430
+ organizationId,
1431
+ ...normalizeOrganizationClosureStartInput(closure)
1432
+ }
1433
+ };
1434
+ }
1435
+ if (request.action === "organization_closure_cancel") {
1436
+ const { action: _action, organizationId: _organizationId, ...closure } = request;
1437
+ return {
1438
+ purpose: input.purpose,
1439
+ ...base,
1440
+ request: {
1441
+ action: request.action,
1442
+ organizationId,
1443
+ ...normalizeOrganizationClosureCancelInput(closure)
1444
+ }
1445
+ };
1446
+ }
1447
+ throw new TypeError("request action is invalid");
1448
+ }
1449
+ default: throw new TypeError("purpose is invalid");
1450
+ }
1451
+ }
1452
+ function normalizeCeremonyHandoff(value) {
1453
+ if (!exact(value, ["expiresAt", "url"]) || typeof value.url !== "string") throw authorityUnavailable();
1454
+ let url;
1455
+ try {
1456
+ url = new URL(value.url);
1457
+ } catch {
1458
+ throw authorityUnavailable();
1459
+ }
1460
+ const local = url.hostname === "localhost" || url.hostname.endsWith(".localhost");
1461
+ if (url.protocol !== "https:" && !(local && url.protocol === "http:") || url.username || url.password || url.pathname !== "/api/v1/auth/ceremony/start" || url.search || !/^#code=[A-Za-z0-9_-]{43}$/.test(url.hash)) throw authorityUnavailable();
1462
+ return {
1463
+ url: url.toString(),
1464
+ expiresAt: date(value.expiresAt)
1465
+ };
1466
+ }
1467
+ function normalizePasskeyId(value) {
1468
+ if (typeof value !== "string" || !idPattern.test(value)) throw new TypeError("passkeyId is invalid");
1469
+ return value;
1470
+ }
1471
+ function normalizePasskeyName(value) {
1472
+ if (typeof value !== "string") throw new TypeError("name is invalid");
1473
+ const name = value.trim();
1474
+ if (!name || name.length > PASSKEY_NAME_MAX_LENGTH || /[\p{Cc}\p{Cf}]/u.test(name)) throw new TypeError("name is invalid");
1475
+ return name;
1476
+ }
1477
+ function normalizePasskeySummary(value) {
1478
+ if (!exact(value, itemKeys) || typeof value.id !== "string" || !idPattern.test(value.id)) throw authorityUnavailable();
1479
+ if (value.name !== null && (typeof value.name !== "string" || value.name.length > PASSKEY_NAME_MAX_LENGTH)) throw authorityUnavailable();
1480
+ if (value.deviceType !== "singleDevice" && value.deviceType !== "multiDevice") throw authorityUnavailable();
1481
+ if (typeof value.backedUp !== "boolean") throw authorityUnavailable();
1482
+ return {
1483
+ id: value.id,
1484
+ name: value.name,
1485
+ createdAt: value.createdAt === null ? null : date(value.createdAt),
1486
+ deviceType: value.deviceType,
1487
+ backedUp: value.backedUp
1488
+ };
1489
+ }
1490
+ function normalizePasskeyInventory(value) {
1491
+ if (!exact(value, ["passkeys", "truncated"]) || !Array.isArray(value.passkeys) || value.passkeys.length > MAX_PASSKEYS || typeof value.truncated !== "boolean") throw authorityUnavailable();
1492
+ const passkeys = value.passkeys.map(normalizePasskeySummary);
1493
+ if (new Set(passkeys.map((passkey) => passkey.id)).size !== passkeys.length) throw authorityUnavailable();
1494
+ return {
1495
+ passkeys,
1496
+ truncated: value.truncated
1497
+ };
1498
+ }
1499
+ function normalizePasskeyRename(value) {
1500
+ if (!exact(value, ["status"]) || value.status !== "renamed") throw authorityUnavailable();
1501
+ }
1502
+ function fromCeremonyHandoffError(value, status, retryAfter) {
1503
+ const code = isObject(value) ? value.code : void 0;
1504
+ if (status === 400 && code === "RETURN_ADDRESS_REFUSED") return new AuthError("ceremony_return_refused", 400);
1505
+ if (status === 400) return new AuthError("invalid_request", 400);
1506
+ if (status === 401) return new AuthError("authentication_required", 401);
1507
+ if (status === 403) return new AuthError("request_origin_denied", 403);
1508
+ if (status === 404) return new AuthError("state_conflict", 409);
1509
+ if (status === 409 && code === "PASSWORD_REQUIRED") return new AuthError("password_sign_in_required", 409);
1510
+ if (status === 409) return new AuthError("state_conflict", 409);
1511
+ if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
1512
+ return authorityUnavailable();
1513
+ }
1514
+ //#endregion
1233
1515
  //#region src/device.ts
1234
1516
  const DEVICE_SCOPE = "openid";
1235
1517
  const GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
@@ -1438,6 +1720,34 @@ function createDeviceAuth(options) {
1438
1720
  mapError: fromAccountAuthorityError
1439
1721
  });
1440
1722
  }
1723
+ async function sessionInventoryRequest(method, path, normalize) {
1724
+ const current = await readToken();
1725
+ if (!current) throw new AuthError("authentication_required", 401);
1726
+ return normalize((await requestJsonResponse(joinURL(authOrigin, "api/v1/auth/sessions", path), {
1727
+ fetch: requestFetch,
1728
+ timeoutMs,
1729
+ method,
1730
+ credentials: "omit",
1731
+ headers: { authorization: `Bearer ${current.accessToken}` },
1732
+ mapError: fromSessionInventoryError
1733
+ })).value);
1734
+ }
1735
+ async function ceremonyRequest(method, path, body, normalize) {
1736
+ const current = await readToken();
1737
+ if (!current) throw new AuthError("authentication_required", 401);
1738
+ return normalize((await requestJsonResponse(joinURL(authOrigin, "api/v1/auth", path), {
1739
+ fetch: requestFetch,
1740
+ timeoutMs,
1741
+ method,
1742
+ credentials: "omit",
1743
+ headers: {
1744
+ authorization: `Bearer ${current.accessToken}`,
1745
+ ...body ? { "content-type": "application/json" } : {}
1746
+ },
1747
+ ...body ? { body } : {},
1748
+ mapError: fromCeremonyHandoffError
1749
+ })).value);
1750
+ }
1441
1751
  async function revoke(path) {
1442
1752
  const current = await readToken();
1443
1753
  if (!current) return;
@@ -1840,9 +2150,60 @@ function createDeviceAuth(options) {
1840
2150
  }
1841
2151
  return serializeAuthority(async () => {
1842
2152
  const previous = await readToken();
1843
- return replaceIssuedResponse((await accountRequest("sign-in/email", body)).value, previous);
2153
+ const response = await accountRequest("sign-in/email", body);
2154
+ if (isTwoFactorChallenge(response.value)) throw new AuthError("two_factor_required", 401);
2155
+ return replaceIssuedResponse(response.value, previous);
1844
2156
  }, true);
1845
2157
  },
2158
+ listSessions() {
2159
+ return serializeAuthority(() => sessionInventoryRequest("GET", "", normalizeSessionInventory));
2160
+ },
2161
+ revokeSession(sessionId) {
2162
+ let id;
2163
+ try {
2164
+ id = normalizeSessionId(sessionId);
2165
+ } catch (error) {
2166
+ return Promise.reject(error);
2167
+ }
2168
+ return serializeAuthority(async () => {
2169
+ await sessionInventoryRequest("POST", `${id}/revoke`, normalizeSessionRevocation);
2170
+ });
2171
+ },
2172
+ revokeOtherSessions() {
2173
+ return serializeAuthority(() => sessionInventoryRequest("POST", "revoke-others", normalizeOtherSessionRevocation));
2174
+ },
2175
+ createCeremonyHandoff(input) {
2176
+ let body;
2177
+ try {
2178
+ body = normalizeCeremonyHandoffInput(input);
2179
+ } catch (error) {
2180
+ return Promise.reject(error);
2181
+ }
2182
+ return serializeAuthority(() => ceremonyRequest("POST", "ceremony-handoffs", body, normalizeCeremonyHandoff));
2183
+ },
2184
+ listPasskeys() {
2185
+ return serializeAuthority(() => ceremonyRequest("GET", "passkeys", void 0, normalizePasskeyInventory));
2186
+ },
2187
+ renamePasskey(passkeyId, name) {
2188
+ let path;
2189
+ let body;
2190
+ try {
2191
+ path = `passkeys/${normalizePasskeyId(passkeyId)}/name`;
2192
+ body = { name: normalizePasskeyName(name) };
2193
+ } catch (error) {
2194
+ return Promise.reject(error);
2195
+ }
2196
+ return serializeAuthority(async () => {
2197
+ await ceremonyRequest("POST", path, body, normalizePasskeyRename);
2198
+ });
2199
+ },
2200
+ getTwoFactorStatus() {
2201
+ return serializeAuthority(async () => {
2202
+ const current = await readToken();
2203
+ if (!current) throw new AuthError("authentication_required", 401);
2204
+ return normalizeTwoFactorStatus((await authenticated("get-session", current)).value);
2205
+ });
2206
+ },
1846
2207
  signInWithSocialIdToken(input) {
1847
2208
  let body;
1848
2209
  try {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { $ as AuthError, A as OrganizationTeamPage, B as ReceivedOrganizationInvitation, C as OrganizationMemberAuthority, D as OrganizationTeam, E as OrganizationPageInput, F as PlatformRoleApplied, G as SendVerificationEmailInput, H as RecentAuthenticationStatus, I as PlatformRoleApproval, J as SocialIdTokenProvider, K as SignInInput, L as PlatformRoleChangeRecentAuthenticationInput, M as PersonalWorkspaceSelection, N as PlatformBootstrapRoleChangeInput, O as OrganizationTeamDisplay, P as PlatformRole, Q as WorkspaceSelection, R as PlatformRoleFirstApproval, S as OrganizationMember, T as OrganizationPage, U as RemovedOrganizationMember, V as ReceivedOrganizationInvitationPage, W as ResentOrganizationInvitation, X as UpdateOrganizationTeamDisplayInput, Y as UpdateOrganizationDisplayInput, Z as UpdateProfileInput, _ as InvitationAcceptance, a as AuthPersistenceDriver, b as OrganizationInvitation, c as AuthUser, d as CreatedOrganization, et as AuthErrorCode, f as CreatedOrganizationMemberInvitation, g as FinuevaAuthClient, h as DriveCredentialInput, i as AuthPersistence, j as OrganizationWorkspaceSelection, k as OrganizationTeamMemberPage, l as CanceledOrganizationInvitation, m as DriveCredential, n as AuthClientOptions, nt as UserApiCredential, o as AuthSession, p as CreatedOrganizationTeam, q as SocialIdTokenInput, r as AuthOrganization, rt as UserApiCredentialInput, s as AuthState, t as AcceptInvitationInput, tt as AuthErrorStatus, u as CreateOrganizationMemberInvitationInput, v as OrganizationDeparture, w as OrganizationMemberPage, x as OrganizationInvitationPage, y as OrganizationDisplay, z as PlatformStatus } from "./types-CrdIcEJ3.js";
1
+ import { $ as PlatformBootstrapRoleChangeInput, A as FinuevaAuthClient, At as AuthError, B as OrganizationMember, C as DeclineInvitationInput, Ct as TwoFactorEnrollment, D as DriveCredential, Dt as UpdateOrganizationTeamDisplayInput, E as DepartedOrganizationMemberPage, Et as UpdateOrganizationDisplayInput, F as OrganizationClosureStartInput, G as OrganizationTeam, H as OrganizationMemberPage, I as OrganizationDeparture, J as OrganizationTeamPage, K as OrganizationTeamDisplay, L as OrganizationDisplay, M as InvitationDecline, Mt as AuthErrorStatus, N as OrganizationClosure, Nt as UserApiCredential, O as DriveCredentialInput, Ot as UpdateProfileInput, P as OrganizationClosureCancelInput, Pt as UserApiCredentialInput, Q as PersonalWorkspaceSelection, R as OrganizationInvitation, S as CreatedOrganizationTeam, St as SuspendedOrganizationMemberStatus, T as DepartedOrganizationMember, Tt as TwoFactorStepUpInput, U as OrganizationPage, V as OrganizationMemberAuthority, W as OrganizationPageInput, X as PasskeyInventory, Y as OrganizationWorkspaceSelection, Z as PasskeySummary, _ as ClosingOrganization, _t as SignInInput, a as AuthPersistence, at as PlatformStatus, b as CreatedOrganization, bt as SuspendedOrganizationMember, c as AuthSessionInventory, ct as RecentAuthenticationStatus, d as AuthUser, dt as ResentOrganizationInvitation, et as PlatformRole, f as CanceledOrganizationInvitation, ft as RestoredOrganizationMember, g as CeremonyReturnInput, gt as SendVerificationEmailInput, h as CeremonyRecentAuthenticationRequest, ht as ScimCredentialState, i as AuthOrganization, it as PlatformRoleFirstApproval, j as InvitationAcceptance, jt as AuthErrorCode, k as EnterpriseConnection, kt as WorkspaceSelection, l as AuthSessionSummary, lt as RemovedOrganizationMember, m as CeremonyHandoffInput, mt as ScimCredentialIssuance, n as AddedOrganizationTeamMember, nt as PlatformRoleApproval, o as AuthPersistenceDriver, ot as ReceivedOrganizationInvitation, p as CeremonyHandoff, pt as RotateScimCredentialInput, q as OrganizationTeamMemberPage, r as AuthClientOptions, rt as PlatformRoleChangeRecentAuthenticationInput, s as AuthSession, st as ReceivedOrganizationInvitationPage, t as AcceptInvitationInput, tt as PlatformRoleApplied, u as AuthState, ut as RemovedOrganizationTeamMember, v as ClosingOrganizationList, vt as SocialIdTokenInput, w as DeletedOrganizationTeam, wt as TwoFactorStatus, x as CreatedOrganizationMemberInvitation, xt as SuspendedOrganizationMemberPage, y as CreateOrganizationMemberInvitationInput, yt as SocialIdTokenProvider, z as OrganizationInvitationPage } from "./types-Cv_qxcBP.js";
2
2
  //#region src/client.d.ts
3
3
  declare function createAuthClient(options: AuthClientOptions): FinuevaAuthClient;
4
4
  //#endregion
5
- export { type AcceptInvitationInput, type AuthClientOptions, AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type AuthPersistence, type AuthPersistenceDriver, type AuthSession, type AuthState, type AuthUser, type CanceledOrganizationInvitation, type CreateOrganizationMemberInvitationInput, type CreatedOrganization, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DriveCredential, type DriveCredentialInput, type FinuevaAuthClient, type InvitationAcceptance, type OrganizationDeparture, type OrganizationDisplay, type OrganizationInvitation, type OrganizationInvitationPage, type OrganizationMember, type OrganizationMemberAuthority, type OrganizationMemberPage, type OrganizationPage, type OrganizationPageInput, type OrganizationTeam, type OrganizationTeamDisplay, type OrganizationTeamMemberPage, type OrganizationTeamPage, type OrganizationWorkspaceSelection, type PersonalWorkspaceSelection, type PlatformBootstrapRoleChangeInput, type PlatformRole, type PlatformRoleApplied, type PlatformRoleApproval, type PlatformRoleChangeRecentAuthenticationInput, type PlatformRoleFirstApproval, type PlatformStatus, type ReceivedOrganizationInvitation, type ReceivedOrganizationInvitationPage, type RecentAuthenticationStatus, type RemovedOrganizationMember, type ResentOrganizationInvitation, type SendVerificationEmailInput, type SignInInput, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UpdateProfileInput, type UserApiCredential, type UserApiCredentialInput, type WorkspaceSelection, createAuthClient };
5
+ export { type AcceptInvitationInput, type AddedOrganizationTeamMember, type AuthClientOptions, AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type AuthPersistence, type AuthPersistenceDriver, type AuthSession, type AuthSessionInventory, type AuthSessionSummary, type AuthState, type AuthUser, type CanceledOrganizationInvitation, type CeremonyHandoff, type CeremonyHandoffInput, type CeremonyRecentAuthenticationRequest, type CeremonyReturnInput, type ClosingOrganization, type ClosingOrganizationList, type CreateOrganizationMemberInvitationInput, type CreatedOrganization, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DeclineInvitationInput, type DeletedOrganizationTeam, type DepartedOrganizationMember, type DepartedOrganizationMemberPage, type DriveCredential, type DriveCredentialInput, type EnterpriseConnection, type FinuevaAuthClient, type InvitationAcceptance, type InvitationDecline, type OrganizationClosure, type OrganizationClosureCancelInput, type OrganizationClosureStartInput, type OrganizationDeparture, type OrganizationDisplay, type OrganizationInvitation, type OrganizationInvitationPage, type OrganizationMember, type OrganizationMemberAuthority, type OrganizationMemberPage, type OrganizationPage, type OrganizationPageInput, type OrganizationTeam, type OrganizationTeamDisplay, type OrganizationTeamMemberPage, type OrganizationTeamPage, type OrganizationWorkspaceSelection, type PasskeyInventory, type PasskeySummary, type PersonalWorkspaceSelection, type PlatformBootstrapRoleChangeInput, type PlatformRole, type PlatformRoleApplied, type PlatformRoleApproval, type PlatformRoleChangeRecentAuthenticationInput, type PlatformRoleFirstApproval, type PlatformStatus, type ReceivedOrganizationInvitation, type ReceivedOrganizationInvitationPage, type RecentAuthenticationStatus, type RemovedOrganizationMember, type RemovedOrganizationTeamMember, type ResentOrganizationInvitation, type RestoredOrganizationMember, type RotateScimCredentialInput, type ScimCredentialIssuance, type ScimCredentialState, type SendVerificationEmailInput, type SignInInput, type SocialIdTokenInput, type SocialIdTokenProvider, type SuspendedOrganizationMember, type SuspendedOrganizationMemberPage, type SuspendedOrganizationMemberStatus, type TwoFactorEnrollment, type TwoFactorStatus, type TwoFactorStepUpInput, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UpdateProfileInput, type UserApiCredential, type UserApiCredentialInput, type WorkspaceSelection, createAuthClient };