@finueva/auth 0.18.1 → 0.19.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/README.md +48 -25
- package/dist/device.d.ts +22 -2
- package/dist/device.js +379 -23
- package/dist/index.d.ts +2 -2
- package/dist/index.js +882 -31
- package/dist/server.d.ts +6 -2
- package/dist/server.js +88 -1
- package/dist/types-BEgD_Js1.d.ts +591 -0
- package/package.json +1 -1
- package/dist/types-CrdIcEJ3.d.ts +0 -351
package/dist/device.js
CHANGED
|
@@ -198,7 +198,18 @@ const messages = {
|
|
|
198
198
|
platform_target_unavailable: "The platform administration target is unavailable.",
|
|
199
199
|
platform_quorum_unavailable: "Platform administration quorum is unavailable.",
|
|
200
200
|
platform_recovery_required: "Platform administration requires separate recovery.",
|
|
201
|
-
identity_authority_unavailable: "Authentication is temporarily unavailable."
|
|
201
|
+
identity_authority_unavailable: "Authentication is temporarily unavailable.",
|
|
202
|
+
two_factor_required: "A second authentication factor is required.",
|
|
203
|
+
two_factor_code_invalid: "The verification code is invalid.",
|
|
204
|
+
two_factor_challenge_expired: "The second-factor challenge has ended. Sign in again.",
|
|
205
|
+
two_factor_locked: "Second-factor verification is temporarily locked.",
|
|
206
|
+
recent_sign_in_required: "A recent sign-in is required.",
|
|
207
|
+
enterprise_recovery_required: "Enterprise administration evidence requires operator recovery.",
|
|
208
|
+
recent_authentication_required: "A ready recent-authentication action is required.",
|
|
209
|
+
organization_closure_confirmation_mismatch: "The confirmation does not match the organization.",
|
|
210
|
+
organization_closure_cancellation_ended: "The closure cancellation period has ended.",
|
|
211
|
+
ceremony_return_refused: "The return address is not registered for this application.",
|
|
212
|
+
password_sign_in_required: "A password sign-in method is required for this passkey change."
|
|
202
213
|
};
|
|
203
214
|
var AuthError = class extends Error {
|
|
204
215
|
code;
|
|
@@ -327,7 +338,7 @@ function normalizeIdInput(value) {
|
|
|
327
338
|
return value;
|
|
328
339
|
}
|
|
329
340
|
function normalizeOrganization(value) {
|
|
330
|
-
exact(value, [
|
|
341
|
+
exact$2(value, [
|
|
331
342
|
"capabilities",
|
|
332
343
|
"id",
|
|
333
344
|
"lifecycle",
|
|
@@ -337,7 +348,7 @@ function normalizeOrganization(value) {
|
|
|
337
348
|
"slug"
|
|
338
349
|
]);
|
|
339
350
|
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, [
|
|
351
|
+
exact$2(value.capabilities, [
|
|
341
352
|
"readInvitations",
|
|
342
353
|
"readMembers",
|
|
343
354
|
"readTeams"
|
|
@@ -399,7 +410,7 @@ function normalizeOrganizationCreationInput(name, slug, idempotencyKey) {
|
|
|
399
410
|
};
|
|
400
411
|
}
|
|
401
412
|
function normalizeCreatedOrganization(value) {
|
|
402
|
-
exact(value, [
|
|
413
|
+
exact$2(value, [
|
|
403
414
|
"id",
|
|
404
415
|
"name",
|
|
405
416
|
"slug"
|
|
@@ -419,7 +430,7 @@ function normalizeOrganizationTeamCreationInput(name, idempotencyKey) {
|
|
|
419
430
|
};
|
|
420
431
|
}
|
|
421
432
|
function normalizeCreatedOrganizationTeam(value) {
|
|
422
|
-
exact(value, ["id", "name"]);
|
|
433
|
+
exact$2(value, ["id", "name"]);
|
|
423
434
|
if (!isId(value.id) || !boundedString(value.name, 255)) throw authorityUnavailable();
|
|
424
435
|
return {
|
|
425
436
|
id: value.id,
|
|
@@ -446,7 +457,7 @@ function normalizeOrganizationMemberInvitationCreationInput(value) {
|
|
|
446
457
|
};
|
|
447
458
|
}
|
|
448
459
|
function normalizeCreatedOrganizationMemberInvitation(value) {
|
|
449
|
-
exact(value, ["expiresAt", "id"]);
|
|
460
|
+
exact$2(value, ["expiresAt", "id"]);
|
|
450
461
|
if (!isId(value.id)) throw authorityUnavailable();
|
|
451
462
|
return {
|
|
452
463
|
id: value.id,
|
|
@@ -454,7 +465,7 @@ function normalizeCreatedOrganizationMemberInvitation(value) {
|
|
|
454
465
|
};
|
|
455
466
|
}
|
|
456
467
|
function normalizeOrganizations(value) {
|
|
457
|
-
exact(value, ["nextCursor", "organizations"]);
|
|
468
|
+
exact$2(value, ["nextCursor", "organizations"]);
|
|
458
469
|
if (!Array.isArray(value.organizations) || value.organizations.length > 100) throw authorityUnavailable();
|
|
459
470
|
return {
|
|
460
471
|
organizations: unique(value.organizations.map(normalizeOrganization), (item) => item.id),
|
|
@@ -462,11 +473,11 @@ function normalizeOrganizations(value) {
|
|
|
462
473
|
};
|
|
463
474
|
}
|
|
464
475
|
function normalizeOrganizationMembers(value) {
|
|
465
|
-
exact(value, ["members", "nextCursor"]);
|
|
476
|
+
exact$2(value, ["members", "nextCursor"]);
|
|
466
477
|
if (!Array.isArray(value.members) || value.members.length > 100) throw authorityUnavailable();
|
|
467
478
|
return {
|
|
468
479
|
members: unique(value.members.map((member) => {
|
|
469
|
-
exact(member, [
|
|
480
|
+
exact$2(member, [
|
|
470
481
|
"email",
|
|
471
482
|
"id",
|
|
472
483
|
"image",
|
|
@@ -495,11 +506,11 @@ function normalizeOrganizationMembers(value) {
|
|
|
495
506
|
};
|
|
496
507
|
}
|
|
497
508
|
function normalizeOrganizationTeams(value) {
|
|
498
|
-
exact(value, ["nextCursor", "teams"]);
|
|
509
|
+
exact$2(value, ["nextCursor", "teams"]);
|
|
499
510
|
if (!Array.isArray(value.teams) || value.teams.length > 100) throw authorityUnavailable();
|
|
500
511
|
return {
|
|
501
512
|
teams: unique(value.teams.map((team) => {
|
|
502
|
-
exact(team, [
|
|
513
|
+
exact$2(team, [
|
|
503
514
|
"category",
|
|
504
515
|
"createdAt",
|
|
505
516
|
"id",
|
|
@@ -517,7 +528,7 @@ function normalizeOrganizationTeams(value) {
|
|
|
517
528
|
};
|
|
518
529
|
}
|
|
519
530
|
function normalizeOrganizationTeamMembers(value) {
|
|
520
|
-
exact(value, ["memberIds", "nextCursor"]);
|
|
531
|
+
exact$2(value, ["memberIds", "nextCursor"]);
|
|
521
532
|
if (!Array.isArray(value.memberIds) || value.memberIds.length > 100) throw authorityUnavailable();
|
|
522
533
|
return {
|
|
523
534
|
memberIds: unique(value.memberIds.map((item) => normalizeResponseId(item)), (item) => item),
|
|
@@ -525,7 +536,7 @@ function normalizeOrganizationTeamMembers(value) {
|
|
|
525
536
|
};
|
|
526
537
|
}
|
|
527
538
|
function normalizeOrganizationInvitation(value) {
|
|
528
|
-
exact(value, [
|
|
539
|
+
exact$2(value, [
|
|
529
540
|
"createdAt",
|
|
530
541
|
"email",
|
|
531
542
|
"expiresAt",
|
|
@@ -536,7 +547,7 @@ function normalizeOrganizationInvitation(value) {
|
|
|
536
547
|
"teamIds"
|
|
537
548
|
]);
|
|
538
549
|
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"]);
|
|
550
|
+
exact$2(value.inviter, ["membershipId", "name"]);
|
|
540
551
|
if (!isId(value.inviter.membershipId) || !boundedString(value.inviter.name, 255)) throw authorityUnavailable();
|
|
541
552
|
return {
|
|
542
553
|
id: value.id,
|
|
@@ -553,7 +564,7 @@ function normalizeOrganizationInvitation(value) {
|
|
|
553
564
|
};
|
|
554
565
|
}
|
|
555
566
|
function normalizeOrganizationInvitations(value) {
|
|
556
|
-
exact(value, ["invitations", "nextCursor"]);
|
|
567
|
+
exact$2(value, ["invitations", "nextCursor"]);
|
|
557
568
|
if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
|
|
558
569
|
return {
|
|
559
570
|
invitations: unique(value.invitations.map(normalizeOrganizationInvitation), (item) => item.id),
|
|
@@ -561,7 +572,7 @@ function normalizeOrganizationInvitations(value) {
|
|
|
561
572
|
};
|
|
562
573
|
}
|
|
563
574
|
function normalizeReceivedInvitation(value) {
|
|
564
|
-
exact(value, [
|
|
575
|
+
exact$2(value, [
|
|
565
576
|
"expiresAt",
|
|
566
577
|
"id",
|
|
567
578
|
"inviterName",
|
|
@@ -570,7 +581,7 @@ function normalizeReceivedInvitation(value) {
|
|
|
570
581
|
"teams"
|
|
571
582
|
]);
|
|
572
583
|
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, [
|
|
584
|
+
exact$2(value.organization, [
|
|
574
585
|
"id",
|
|
575
586
|
"logo",
|
|
576
587
|
"name",
|
|
@@ -587,7 +598,7 @@ function normalizeReceivedInvitation(value) {
|
|
|
587
598
|
},
|
|
588
599
|
role: value.role,
|
|
589
600
|
teams: unique(value.teams.map((team) => {
|
|
590
|
-
exact(team, ["id", "name"]);
|
|
601
|
+
exact$2(team, ["id", "name"]);
|
|
591
602
|
if (!isId(team.id) || !boundedString(team.name, 255)) throw authorityUnavailable();
|
|
592
603
|
return {
|
|
593
604
|
id: team.id,
|
|
@@ -599,7 +610,7 @@ function normalizeReceivedInvitation(value) {
|
|
|
599
610
|
};
|
|
600
611
|
}
|
|
601
612
|
function normalizeReceivedInvitations(value) {
|
|
602
|
-
exact(value, ["invitations", "nextCursor"]);
|
|
613
|
+
exact$2(value, ["invitations", "nextCursor"]);
|
|
603
614
|
if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
|
|
604
615
|
return {
|
|
605
616
|
invitations: unique(value.invitations.map(normalizeReceivedInvitation), (item) => item.id),
|
|
@@ -657,8 +668,35 @@ function fromOrganizationMutationAuthorityError(value, status, retryAfter) {
|
|
|
657
668
|
if (status === 403 && code === "REQUEST_ORIGIN_DENIED") return new AuthError("request_origin_denied", 403);
|
|
658
669
|
return fromOrganizationReadAuthorityError(value, status);
|
|
659
670
|
}
|
|
671
|
+
function normalizeOrganizationClosureStartInput(value) {
|
|
672
|
+
if (!isObject(value) || Object.keys(value).sort().join(",") !== "confirmationName,idempotencyKey") throw new TypeError("organization closure input is invalid");
|
|
673
|
+
if (!boundedString(value.confirmationName, 255)) throw new TypeError("confirmationName is invalid");
|
|
674
|
+
return {
|
|
675
|
+
confirmationName: value.confirmationName,
|
|
676
|
+
idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey)
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
function normalizeOrganizationClosureCancelInput(value) {
|
|
680
|
+
if (!isObject(value) || Object.keys(value).join(",") !== "idempotencyKey") throw new TypeError("organization closure cancellation input is invalid");
|
|
681
|
+
return { idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey) };
|
|
682
|
+
}
|
|
683
|
+
function normalizeOrganizationOwnershipTransferInput(value) {
|
|
684
|
+
if (!isObject(value) || Object.keys(value).sort().join(",") !== "expectedActorAuthorityRevision,expectedOutgoingOwnerAuthorityRevision,expectedSuccessorAuthorityRevision,idempotencyKey,outgoingOwnerMembershipId,outgoingOwnerRole,successorMembershipId") throw new TypeError("organization ownership transfer input is invalid");
|
|
685
|
+
if (!isId(value.outgoingOwnerMembershipId) || !isId(value.successorMembershipId)) throw new TypeError("ownership transfer membership is invalid");
|
|
686
|
+
if (value.outgoingOwnerMembershipId === value.successorMembershipId) throw new TypeError("ownership transfer memberships must differ");
|
|
687
|
+
if (value.outgoingOwnerRole !== "admin" && value.outgoingOwnerRole !== "member") throw new TypeError("outgoingOwnerRole is invalid");
|
|
688
|
+
return {
|
|
689
|
+
outgoingOwnerMembershipId: value.outgoingOwnerMembershipId,
|
|
690
|
+
successorMembershipId: value.successorMembershipId,
|
|
691
|
+
outgoingOwnerRole: value.outgoingOwnerRole,
|
|
692
|
+
expectedActorAuthorityRevision: normalizeAuthorityRevision(value.expectedActorAuthorityRevision, "expectedActorAuthorityRevision"),
|
|
693
|
+
expectedOutgoingOwnerAuthorityRevision: normalizeAuthorityRevision(value.expectedOutgoingOwnerAuthorityRevision, "expectedOutgoingOwnerAuthorityRevision", true),
|
|
694
|
+
expectedSuccessorAuthorityRevision: normalizeAuthorityRevision(value.expectedSuccessorAuthorityRevision, "expectedSuccessorAuthorityRevision", true),
|
|
695
|
+
idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey)
|
|
696
|
+
};
|
|
697
|
+
}
|
|
660
698
|
function normalizeOrganizationMemberAuthority(value, organizationId, memberId) {
|
|
661
|
-
exact(value, [
|
|
699
|
+
exact$2(value, [
|
|
662
700
|
"organizationId",
|
|
663
701
|
"actor",
|
|
664
702
|
"target"
|
|
@@ -676,7 +714,7 @@ function normalizeOrganizationMemberAuthority(value, organizationId, memberId) {
|
|
|
676
714
|
};
|
|
677
715
|
}
|
|
678
716
|
function normalizeOrganizationAuthorityMemberOutcome(value, includesStatus = false) {
|
|
679
|
-
exact(value, [
|
|
717
|
+
exact$2(value, [
|
|
680
718
|
"memberId",
|
|
681
719
|
"manualRole",
|
|
682
720
|
"role",
|
|
@@ -691,10 +729,18 @@ function normalizeOrganizationAuthorityMemberOutcome(value, includesStatus = fal
|
|
|
691
729
|
authorityRevision: normalizeAuthorityResultRevision(value.authorityRevision)
|
|
692
730
|
};
|
|
693
731
|
}
|
|
732
|
+
function normalizeAuthorityRevision(value, name, incremented = false) {
|
|
733
|
+
if (!Number.isSafeInteger(value) || value < 0 || value >= Number.MAX_SAFE_INTEGER - (incremented ? 1 : 0)) throw new TypeError(`${name} is invalid`);
|
|
734
|
+
return value;
|
|
735
|
+
}
|
|
694
736
|
function normalizeAuthorityResultRevision(value) {
|
|
695
737
|
if (!Number.isSafeInteger(value) || value < 0 || value >= Number.MAX_SAFE_INTEGER) throw authorityUnavailable();
|
|
696
738
|
return value;
|
|
697
739
|
}
|
|
740
|
+
function normalizeAuthorityIdempotencyKey(value) {
|
|
741
|
+
if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value)) throw new TypeError("idempotencyKey is invalid");
|
|
742
|
+
return value;
|
|
743
|
+
}
|
|
698
744
|
function mapError(code, status) {
|
|
699
745
|
if (code === "authentication_required") return {
|
|
700
746
|
code,
|
|
@@ -769,7 +815,7 @@ function normalizeProfileImage(value) {
|
|
|
769
815
|
function isId(value) {
|
|
770
816
|
return typeof value === "string" && id.test(value);
|
|
771
817
|
}
|
|
772
|
-
function exact(value, keys) {
|
|
818
|
+
function exact$2(value, keys) {
|
|
773
819
|
if (!isObject(value) || Object.keys(value).sort().join(",") !== [...keys].sort().join(",")) throw authorityUnavailable();
|
|
774
820
|
}
|
|
775
821
|
function boundedString(value, maximum) {
|
|
@@ -1230,6 +1276,237 @@ async function readJson(response, maximum = MAX_RESPONSE_BYTES) {
|
|
|
1230
1276
|
}
|
|
1231
1277
|
}
|
|
1232
1278
|
//#endregion
|
|
1279
|
+
//#region src/two-factor.ts
|
|
1280
|
+
function isTwoFactorChallenge(value) {
|
|
1281
|
+
return isObject(value) && value.twoFactorRedirect === true;
|
|
1282
|
+
}
|
|
1283
|
+
function normalizeTwoFactorStatus(value) {
|
|
1284
|
+
if (value === null) throw new AuthError("authentication_required", 401);
|
|
1285
|
+
if (!isObject(value) || !isObject(value.user) || typeof value.user.twoFactorEnabled !== "boolean") throw authorityUnavailable();
|
|
1286
|
+
return { enabled: value.user.twoFactorEnabled };
|
|
1287
|
+
}
|
|
1288
|
+
//#endregion
|
|
1289
|
+
//#region src/sessions.ts
|
|
1290
|
+
const idPattern$1 = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
|
|
1291
|
+
const MAX_SESSIONS = 50;
|
|
1292
|
+
const itemKeys$1 = [
|
|
1293
|
+
"createdAt",
|
|
1294
|
+
"current",
|
|
1295
|
+
"expiresAt",
|
|
1296
|
+
"id",
|
|
1297
|
+
"ipAddress",
|
|
1298
|
+
"updatedAt",
|
|
1299
|
+
"userAgent"
|
|
1300
|
+
];
|
|
1301
|
+
function exact$1(value, keys) {
|
|
1302
|
+
return isObject(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
1303
|
+
}
|
|
1304
|
+
function date$1(value) {
|
|
1305
|
+
if (typeof value !== "string") throw authorityUnavailable();
|
|
1306
|
+
const parsed = new Date(value);
|
|
1307
|
+
if (!Number.isFinite(parsed.getTime()) || parsed.toISOString() !== value) throw authorityUnavailable();
|
|
1308
|
+
return parsed;
|
|
1309
|
+
}
|
|
1310
|
+
function text(value, maximum) {
|
|
1311
|
+
if (value === null) return null;
|
|
1312
|
+
if (typeof value !== "string" || value.length === 0 || value.length > maximum || /[^\x20-\x7e]/.test(value)) throw authorityUnavailable();
|
|
1313
|
+
return value;
|
|
1314
|
+
}
|
|
1315
|
+
function normalizeSessionId(value) {
|
|
1316
|
+
if (typeof value !== "string" || !idPattern$1.test(value)) throw new TypeError("sessionId is invalid");
|
|
1317
|
+
return value;
|
|
1318
|
+
}
|
|
1319
|
+
function normalizeSessionSummary(value) {
|
|
1320
|
+
if (!exact$1(value, itemKeys$1) || typeof value.id !== "string" || !idPattern$1.test(value.id)) throw authorityUnavailable();
|
|
1321
|
+
if (typeof value.current !== "boolean") throw authorityUnavailable();
|
|
1322
|
+
return {
|
|
1323
|
+
id: value.id,
|
|
1324
|
+
current: value.current,
|
|
1325
|
+
createdAt: date$1(value.createdAt),
|
|
1326
|
+
updatedAt: date$1(value.updatedAt),
|
|
1327
|
+
expiresAt: date$1(value.expiresAt),
|
|
1328
|
+
userAgent: text(value.userAgent, 512),
|
|
1329
|
+
ipAddress: text(value.ipAddress, 64)
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
function normalizeSessionInventory(value) {
|
|
1333
|
+
if (!exact$1(value, ["sessions", "truncated"]) || !Array.isArray(value.sessions) || value.sessions.length > MAX_SESSIONS || typeof value.truncated !== "boolean") throw authorityUnavailable();
|
|
1334
|
+
const sessions = value.sessions.map(normalizeSessionSummary);
|
|
1335
|
+
if (new Set(sessions.map((session) => session.id)).size !== sessions.length) throw authorityUnavailable();
|
|
1336
|
+
if (sessions.filter((session) => session.current).length !== 1) throw authorityUnavailable();
|
|
1337
|
+
return {
|
|
1338
|
+
sessions,
|
|
1339
|
+
truncated: value.truncated
|
|
1340
|
+
};
|
|
1341
|
+
}
|
|
1342
|
+
function normalizeSessionRevocation(value) {
|
|
1343
|
+
if (!exact$1(value, ["status"]) || value.status !== "revoked") throw authorityUnavailable();
|
|
1344
|
+
}
|
|
1345
|
+
function normalizeOtherSessionRevocation(value) {
|
|
1346
|
+
if (!exact$1(value, ["revoked"]) || !Number.isSafeInteger(value.revoked) || value.revoked < 0) throw authorityUnavailable();
|
|
1347
|
+
return { revoked: value.revoked };
|
|
1348
|
+
}
|
|
1349
|
+
function fromSessionInventoryError(_value, status, retryAfter) {
|
|
1350
|
+
if (status === 400) return new AuthError("invalid_request", 400);
|
|
1351
|
+
if (status === 401) return new AuthError("authentication_required", 401);
|
|
1352
|
+
if (status === 403) return new AuthError("request_origin_denied", 403);
|
|
1353
|
+
if (status === 404 || status === 409) return new AuthError("state_conflict", 409);
|
|
1354
|
+
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
1355
|
+
return authorityUnavailable();
|
|
1356
|
+
}
|
|
1357
|
+
//#endregion
|
|
1358
|
+
//#region src/passkeys.ts
|
|
1359
|
+
const idPattern = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
|
|
1360
|
+
const MAX_PASSKEYS = 50;
|
|
1361
|
+
const MAX_RETURN_BYTES = 2048;
|
|
1362
|
+
const PASSKEY_NAME_MAX_LENGTH = 64;
|
|
1363
|
+
const itemKeys = [
|
|
1364
|
+
"backedUp",
|
|
1365
|
+
"createdAt",
|
|
1366
|
+
"deviceType",
|
|
1367
|
+
"id",
|
|
1368
|
+
"name"
|
|
1369
|
+
];
|
|
1370
|
+
function exact(value, keys) {
|
|
1371
|
+
return isObject(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
1372
|
+
}
|
|
1373
|
+
function date(value) {
|
|
1374
|
+
if (typeof value !== "string") throw authorityUnavailable();
|
|
1375
|
+
const parsed = new Date(value);
|
|
1376
|
+
if (!Number.isFinite(parsed.getTime()) || parsed.toISOString() !== value) throw authorityUnavailable();
|
|
1377
|
+
return parsed;
|
|
1378
|
+
}
|
|
1379
|
+
function returnInput(value) {
|
|
1380
|
+
if (!isObject(value)) throw new TypeError("ceremony input is invalid");
|
|
1381
|
+
const { applicationId, returnTo } = value;
|
|
1382
|
+
if (typeof applicationId !== "string" || !idPattern.test(applicationId)) throw new TypeError("applicationId is invalid");
|
|
1383
|
+
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");
|
|
1384
|
+
return {
|
|
1385
|
+
applicationId,
|
|
1386
|
+
returnTo
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
function normalizeCeremonyHandoffInput(value) {
|
|
1390
|
+
const base = returnInput(value);
|
|
1391
|
+
const input = value;
|
|
1392
|
+
switch (input.purpose) {
|
|
1393
|
+
case "passkey_enrollment": return {
|
|
1394
|
+
purpose: input.purpose,
|
|
1395
|
+
...base
|
|
1396
|
+
};
|
|
1397
|
+
case "passkey_removal": return {
|
|
1398
|
+
purpose: input.purpose,
|
|
1399
|
+
...base,
|
|
1400
|
+
passkeyId: normalizePasskeyId(input.passkeyId)
|
|
1401
|
+
};
|
|
1402
|
+
case "recent_authentication": {
|
|
1403
|
+
const request = input.request;
|
|
1404
|
+
if (!isObject(request)) throw new TypeError("request is invalid");
|
|
1405
|
+
const organizationId = normalizeIdInput(request.organizationId);
|
|
1406
|
+
if (request.action === "organization_ownership_transfer") {
|
|
1407
|
+
const { action: _action, organizationId: _organizationId, ...transfer } = request;
|
|
1408
|
+
return {
|
|
1409
|
+
purpose: input.purpose,
|
|
1410
|
+
...base,
|
|
1411
|
+
request: {
|
|
1412
|
+
action: request.action,
|
|
1413
|
+
organizationId,
|
|
1414
|
+
...normalizeOrganizationOwnershipTransferInput(transfer)
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
if (request.action === "organization_closure_start") {
|
|
1419
|
+
const { action: _action, organizationId: _organizationId, ...closure } = request;
|
|
1420
|
+
return {
|
|
1421
|
+
purpose: input.purpose,
|
|
1422
|
+
...base,
|
|
1423
|
+
request: {
|
|
1424
|
+
action: request.action,
|
|
1425
|
+
organizationId,
|
|
1426
|
+
...normalizeOrganizationClosureStartInput(closure)
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
if (request.action === "organization_closure_cancel") {
|
|
1431
|
+
const { action: _action, organizationId: _organizationId, ...closure } = request;
|
|
1432
|
+
return {
|
|
1433
|
+
purpose: input.purpose,
|
|
1434
|
+
...base,
|
|
1435
|
+
request: {
|
|
1436
|
+
action: request.action,
|
|
1437
|
+
organizationId,
|
|
1438
|
+
...normalizeOrganizationClosureCancelInput(closure)
|
|
1439
|
+
}
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
throw new TypeError("request action is invalid");
|
|
1443
|
+
}
|
|
1444
|
+
default: throw new TypeError("purpose is invalid");
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
function normalizeCeremonyHandoff(value) {
|
|
1448
|
+
if (!exact(value, ["expiresAt", "url"]) || typeof value.url !== "string") throw authorityUnavailable();
|
|
1449
|
+
let url;
|
|
1450
|
+
try {
|
|
1451
|
+
url = new URL(value.url);
|
|
1452
|
+
} catch {
|
|
1453
|
+
throw authorityUnavailable();
|
|
1454
|
+
}
|
|
1455
|
+
const local = url.hostname === "localhost" || url.hostname.endsWith(".localhost");
|
|
1456
|
+
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();
|
|
1457
|
+
return {
|
|
1458
|
+
url: url.toString(),
|
|
1459
|
+
expiresAt: date(value.expiresAt)
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
function normalizePasskeyId(value) {
|
|
1463
|
+
if (typeof value !== "string" || !idPattern.test(value)) throw new TypeError("passkeyId is invalid");
|
|
1464
|
+
return value;
|
|
1465
|
+
}
|
|
1466
|
+
function normalizePasskeyName(value) {
|
|
1467
|
+
if (typeof value !== "string") throw new TypeError("name is invalid");
|
|
1468
|
+
const name = value.trim();
|
|
1469
|
+
if (!name || name.length > PASSKEY_NAME_MAX_LENGTH || /[\p{Cc}\p{Cf}]/u.test(name)) throw new TypeError("name is invalid");
|
|
1470
|
+
return name;
|
|
1471
|
+
}
|
|
1472
|
+
function normalizePasskeySummary(value) {
|
|
1473
|
+
if (!exact(value, itemKeys) || typeof value.id !== "string" || !idPattern.test(value.id)) throw authorityUnavailable();
|
|
1474
|
+
if (value.name !== null && (typeof value.name !== "string" || value.name.length > PASSKEY_NAME_MAX_LENGTH)) throw authorityUnavailable();
|
|
1475
|
+
if (value.deviceType !== "singleDevice" && value.deviceType !== "multiDevice") throw authorityUnavailable();
|
|
1476
|
+
if (typeof value.backedUp !== "boolean") throw authorityUnavailable();
|
|
1477
|
+
return {
|
|
1478
|
+
id: value.id,
|
|
1479
|
+
name: value.name,
|
|
1480
|
+
createdAt: value.createdAt === null ? null : date(value.createdAt),
|
|
1481
|
+
deviceType: value.deviceType,
|
|
1482
|
+
backedUp: value.backedUp
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
function normalizePasskeyInventory(value) {
|
|
1486
|
+
if (!exact(value, ["passkeys", "truncated"]) || !Array.isArray(value.passkeys) || value.passkeys.length > MAX_PASSKEYS || typeof value.truncated !== "boolean") throw authorityUnavailable();
|
|
1487
|
+
const passkeys = value.passkeys.map(normalizePasskeySummary);
|
|
1488
|
+
if (new Set(passkeys.map((passkey) => passkey.id)).size !== passkeys.length) throw authorityUnavailable();
|
|
1489
|
+
return {
|
|
1490
|
+
passkeys,
|
|
1491
|
+
truncated: value.truncated
|
|
1492
|
+
};
|
|
1493
|
+
}
|
|
1494
|
+
function normalizePasskeyRename(value) {
|
|
1495
|
+
if (!exact(value, ["status"]) || value.status !== "renamed") throw authorityUnavailable();
|
|
1496
|
+
}
|
|
1497
|
+
function fromCeremonyHandoffError(value, status, retryAfter) {
|
|
1498
|
+
const code = isObject(value) ? value.code : void 0;
|
|
1499
|
+
if (status === 400 && code === "RETURN_ADDRESS_REFUSED") return new AuthError("ceremony_return_refused", 400);
|
|
1500
|
+
if (status === 400) return new AuthError("invalid_request", 400);
|
|
1501
|
+
if (status === 401) return new AuthError("authentication_required", 401);
|
|
1502
|
+
if (status === 403) return new AuthError("request_origin_denied", 403);
|
|
1503
|
+
if (status === 404) return new AuthError("state_conflict", 409);
|
|
1504
|
+
if (status === 409 && code === "PASSWORD_REQUIRED") return new AuthError("password_sign_in_required", 409);
|
|
1505
|
+
if (status === 409) return new AuthError("state_conflict", 409);
|
|
1506
|
+
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
1507
|
+
return authorityUnavailable();
|
|
1508
|
+
}
|
|
1509
|
+
//#endregion
|
|
1233
1510
|
//#region src/device.ts
|
|
1234
1511
|
const DEVICE_SCOPE = "openid";
|
|
1235
1512
|
const GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
@@ -1438,6 +1715,34 @@ function createDeviceAuth(options) {
|
|
|
1438
1715
|
mapError: fromAccountAuthorityError
|
|
1439
1716
|
});
|
|
1440
1717
|
}
|
|
1718
|
+
async function sessionInventoryRequest(method, path, normalize) {
|
|
1719
|
+
const current = await readToken();
|
|
1720
|
+
if (!current) throw new AuthError("authentication_required", 401);
|
|
1721
|
+
return normalize((await requestJsonResponse(joinURL(authOrigin, "api/v1/auth/sessions", path), {
|
|
1722
|
+
fetch: requestFetch,
|
|
1723
|
+
timeoutMs,
|
|
1724
|
+
method,
|
|
1725
|
+
credentials: "omit",
|
|
1726
|
+
headers: { authorization: `Bearer ${current.accessToken}` },
|
|
1727
|
+
mapError: fromSessionInventoryError
|
|
1728
|
+
})).value);
|
|
1729
|
+
}
|
|
1730
|
+
async function ceremonyRequest(method, path, body, normalize) {
|
|
1731
|
+
const current = await readToken();
|
|
1732
|
+
if (!current) throw new AuthError("authentication_required", 401);
|
|
1733
|
+
return normalize((await requestJsonResponse(joinURL(authOrigin, "api/v1/auth", path), {
|
|
1734
|
+
fetch: requestFetch,
|
|
1735
|
+
timeoutMs,
|
|
1736
|
+
method,
|
|
1737
|
+
credentials: "omit",
|
|
1738
|
+
headers: {
|
|
1739
|
+
authorization: `Bearer ${current.accessToken}`,
|
|
1740
|
+
...body ? { "content-type": "application/json" } : {}
|
|
1741
|
+
},
|
|
1742
|
+
...body ? { body } : {},
|
|
1743
|
+
mapError: fromCeremonyHandoffError
|
|
1744
|
+
})).value);
|
|
1745
|
+
}
|
|
1441
1746
|
async function revoke(path) {
|
|
1442
1747
|
const current = await readToken();
|
|
1443
1748
|
if (!current) return;
|
|
@@ -1840,9 +2145,60 @@ function createDeviceAuth(options) {
|
|
|
1840
2145
|
}
|
|
1841
2146
|
return serializeAuthority(async () => {
|
|
1842
2147
|
const previous = await readToken();
|
|
1843
|
-
|
|
2148
|
+
const response = await accountRequest("sign-in/email", body);
|
|
2149
|
+
if (isTwoFactorChallenge(response.value)) throw new AuthError("two_factor_required", 401);
|
|
2150
|
+
return replaceIssuedResponse(response.value, previous);
|
|
1844
2151
|
}, true);
|
|
1845
2152
|
},
|
|
2153
|
+
listSessions() {
|
|
2154
|
+
return serializeAuthority(() => sessionInventoryRequest("GET", "", normalizeSessionInventory));
|
|
2155
|
+
},
|
|
2156
|
+
revokeSession(sessionId) {
|
|
2157
|
+
let id;
|
|
2158
|
+
try {
|
|
2159
|
+
id = normalizeSessionId(sessionId);
|
|
2160
|
+
} catch (error) {
|
|
2161
|
+
return Promise.reject(error);
|
|
2162
|
+
}
|
|
2163
|
+
return serializeAuthority(async () => {
|
|
2164
|
+
await sessionInventoryRequest("POST", `${id}/revoke`, normalizeSessionRevocation);
|
|
2165
|
+
});
|
|
2166
|
+
},
|
|
2167
|
+
revokeOtherSessions() {
|
|
2168
|
+
return serializeAuthority(() => sessionInventoryRequest("POST", "revoke-others", normalizeOtherSessionRevocation));
|
|
2169
|
+
},
|
|
2170
|
+
createCeremonyHandoff(input) {
|
|
2171
|
+
let body;
|
|
2172
|
+
try {
|
|
2173
|
+
body = normalizeCeremonyHandoffInput(input);
|
|
2174
|
+
} catch (error) {
|
|
2175
|
+
return Promise.reject(error);
|
|
2176
|
+
}
|
|
2177
|
+
return serializeAuthority(() => ceremonyRequest("POST", "ceremony-handoffs", body, normalizeCeremonyHandoff));
|
|
2178
|
+
},
|
|
2179
|
+
listPasskeys() {
|
|
2180
|
+
return serializeAuthority(() => ceremonyRequest("GET", "passkeys", void 0, normalizePasskeyInventory));
|
|
2181
|
+
},
|
|
2182
|
+
renamePasskey(passkeyId, name) {
|
|
2183
|
+
let path;
|
|
2184
|
+
let body;
|
|
2185
|
+
try {
|
|
2186
|
+
path = `passkeys/${normalizePasskeyId(passkeyId)}/name`;
|
|
2187
|
+
body = { name: normalizePasskeyName(name) };
|
|
2188
|
+
} catch (error) {
|
|
2189
|
+
return Promise.reject(error);
|
|
2190
|
+
}
|
|
2191
|
+
return serializeAuthority(async () => {
|
|
2192
|
+
await ceremonyRequest("POST", path, body, normalizePasskeyRename);
|
|
2193
|
+
});
|
|
2194
|
+
},
|
|
2195
|
+
getTwoFactorStatus() {
|
|
2196
|
+
return serializeAuthority(async () => {
|
|
2197
|
+
const current = await readToken();
|
|
2198
|
+
if (!current) throw new AuthError("authentication_required", 401);
|
|
2199
|
+
return normalizeTwoFactorStatus((await authenticated("get-session", current)).value);
|
|
2200
|
+
});
|
|
2201
|
+
},
|
|
1846
2202
|
signInWithSocialIdToken(input) {
|
|
1847
2203
|
let body;
|
|
1848
2204
|
try {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as
|
|
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-BEgD_Js1.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 };
|