@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/README.md +60 -25
- package/dist/device.d.ts +22 -2
- package/dist/device.js +384 -23
- package/dist/index.d.ts +2 -2
- package/dist/index.js +887 -31
- package/dist/server.d.ts +25 -2
- package/dist/server.js +349 -176
- package/dist/types-Cv_qxcBP.d.ts +591 -0
- package/package.json +1 -1
- package/dist/types-CrdIcEJ3.d.ts +0 -351
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
|
-
|
|
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
|
|
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 };
|