@finueva/auth 0.19.0 → 0.21.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 +12 -0
- package/dist/device.d.ts +1 -1
- package/dist/device.js +14 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +142 -1
- package/dist/server.d.ts +21 -2
- package/dist/server.js +270 -176
- package/dist/{types-BEgD_Js1.d.ts → types-sJ_vACZ3.d.ts} +55 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -307,6 +307,18 @@ return new Response(null, { status: 303, headers });
|
|
|
307
307
|
|
|
308
308
|
Call `applyCookies()` after server `signOut()`, `acceptInvitation()`, and `signInWithSocialIdToken()`.
|
|
309
309
|
|
|
310
|
+
## Recover A Google Account Conflict
|
|
311
|
+
|
|
312
|
+
Use the request-scoped server client. If Google sign-in reports an account conflict, call `startGoogleAccountRecovery({ idToken: { token, nonce } })`. Auth verifies the Google identity and confirms that an existing verified password account requires linking. A generic sign-in error alone does not authorize recovery.
|
|
313
|
+
|
|
314
|
+
The result contains an opaque `recoveryToken` and an ISO `expiresAt`. Keep the result and Google ID token in short-lived encrypted server-managed state. Do not put them in URLs, logs, or browser storage.
|
|
315
|
+
|
|
316
|
+
Ask the user to sign in to the existing account with its password. Complete the configured second factor. Then create a new request-scoped client with that session and call `completeGoogleAccountRecovery({ recoveryToken, idToken: { token, nonce } })`. Auth requires a fresh password authentication after the recovery request. An old session or a different account cannot complete recovery. The result is `{ linked: true }`; the current session remains in use.
|
|
317
|
+
|
|
318
|
+
If completion returns `google_recovery_in_progress`, retain the current session and recovery state. A retry can confirm a committed link. Auth does not repeat an uncertain linking mutation. If the original attempt cannot finish, wait for its ten-minute expiry before restarting.
|
|
319
|
+
|
|
320
|
+
Recovery is cookie-only and bound to the registered app origin. It does not enable implicit linking or link users by an email match alone. If recovery expires, restart Google sign-in. If email verification is required, complete the existing account's verification first.
|
|
321
|
+
|
|
310
322
|
## Resolve A Drive Recipient
|
|
311
323
|
|
|
312
324
|
Use the separate server client. Before lookup, Drive must check the caller's current permission to manage the item's shares. Recipient resolution does not grant file access.
|
package/dist/device.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as
|
|
1
|
+
import { $ as PasskeyInventory, At as UpdateOrganizationDisplayInput, B as OrganizationDisplay, C as CreatedOrganizationTeam, Dt as TwoFactorStatus, Ft as AuthErrorCode, G as OrganizationMemberPage, H as OrganizationInvitationPage, It as AuthErrorStatus, J as OrganizationTeam, K as OrganizationPage, Lt as UserApiCredential, Mt as UpdateProfileInput, O as DriveCredential, Pt as AuthError, Rt as UserApiCredentialInput, S as CreatedOrganizationMemberInvitation, St as SocialIdTokenProvider, U as OrganizationMember, V as OrganizationInvitation, W as OrganizationMemberAuthority, X as OrganizationTeamMemberPage, Y as OrganizationTeamDisplay, Z as OrganizationTeamPage, b as CreateOrganizationMemberInvitationInput, c as AuthSessionInventory, i as AuthOrganization, jt as UpdateOrganizationTeamDisplayInput, k as DriveCredentialInput, lt as ReceivedOrganizationInvitation, m as CeremonyHandoffInput, p as CeremonyHandoff, q as OrganizationPageInput, s as AuthSession, ut as ReceivedOrganizationInvitationPage, x as CreatedOrganization, xt as SocialIdTokenInput } from "./types-sJ_vACZ3.js";
|
|
2
2
|
//#region src/device.d.ts
|
|
3
3
|
type DeviceAuthorizationErrorCode = "device_access_denied" | "device_authorization_cancelled" | "device_code_expired" | "invalid_device_authorization" | "identity_authority_unavailable";
|
|
4
4
|
declare class DeviceAuthorizationError extends Error {
|
package/dist/device.js
CHANGED
|
@@ -178,6 +178,12 @@ 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
|
+
social_signup_required: "No account is available for this social sign-in. Start sign-up to create one.",
|
|
182
|
+
google_recovery_in_progress: "A Google connection is already being completed. Return to that sign-in, or wait up to ten minutes and restart.",
|
|
183
|
+
google_recovery_not_required: "Google account recovery is not required.",
|
|
184
|
+
google_recovery_invalid: "The Google account recovery request is invalid.",
|
|
185
|
+
google_recovery_expired: "Google account recovery has expired. Start Google sign-in again.",
|
|
186
|
+
google_recovery_account_mismatch: "Sign in to the existing account associated with this Google identity.",
|
|
181
187
|
password_reset_invalid: "The password reset request is invalid.",
|
|
182
188
|
authentication_required: "Authentication is required.",
|
|
183
189
|
request_origin_denied: "The request origin is not allowed.",
|
|
@@ -193,6 +199,7 @@ const messages = {
|
|
|
193
199
|
organization_context_too_large: "The organization context is too large.",
|
|
194
200
|
credential_rate_limited: "Credential requests are temporarily limited.",
|
|
195
201
|
auth_request_rate_limited: "Authentication requests are temporarily limited.",
|
|
202
|
+
organization_slug_unavailable: "The organization address is unavailable.",
|
|
196
203
|
state_conflict: "The authentication state conflicts with the request.",
|
|
197
204
|
access_denied: "Access is denied.",
|
|
198
205
|
platform_target_unavailable: "The platform administration target is unavailable.",
|
|
@@ -648,7 +655,12 @@ function fromAccountAuthorityError(value, status, retryAfter) {
|
|
|
648
655
|
function fromSocialIdTokenAuthorityError(value, status, retryAfter) {
|
|
649
656
|
const code = isObject(value) && typeof value.code === "string" ? value.code : void 0;
|
|
650
657
|
if (code === "INVALID_TOKEN" || code === "FAILED_TO_GET_USER_INFO" || code === "USER_EMAIL_NOT_FOUND") return new AuthError("invalid_credentials", 401);
|
|
651
|
-
if (code === "OAUTH_LINK_ERROR")
|
|
658
|
+
if (code === "OAUTH_LINK_ERROR") {
|
|
659
|
+
const message = isObject(value) && typeof value.message === "string" ? value.message : void 0;
|
|
660
|
+
if (message === "account not linked") return new AuthError("account_conflict", 409);
|
|
661
|
+
if (message === "signup disabled") return new AuthError("social_signup_required", 409);
|
|
662
|
+
return authorityUnavailable();
|
|
663
|
+
}
|
|
652
664
|
return fromAccountAuthorityError(value, status, retryAfter);
|
|
653
665
|
}
|
|
654
666
|
function authorityUnavailable() {
|
|
@@ -662,6 +674,7 @@ function fromOrganizationReadAuthorityError(value, status) {
|
|
|
662
674
|
}
|
|
663
675
|
function fromOrganizationMutationAuthorityError(value, status, retryAfter) {
|
|
664
676
|
if (status === 400 || status === 413 || status === 415) return new AuthError("invalid_request", 400);
|
|
677
|
+
if (status === 409 && isObject(value) && value.code === "ORGANIZATION_SLUG_UNAVAILABLE") return new AuthError("organization_slug_unavailable", 409);
|
|
665
678
|
if (status === 409) return new AuthError("state_conflict", 409);
|
|
666
679
|
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
667
680
|
const code = isObject(value) && typeof value.code === "string" ? value.code : void 0;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as PasskeyInventory, A as EnterpriseConnection, At as UpdateOrganizationDisplayInput, B as OrganizationDisplay, C as CreatedOrganizationTeam, Ct as SuspendedOrganizationMember, D as DepartedOrganizationMemberPage, Dt as TwoFactorStatus, E as DepartedOrganizationMember, Et as TwoFactorEnrollment, F as InvitationDecline, Ft as AuthErrorCode, G as OrganizationMemberPage, H as OrganizationInvitationPage, I as OrganizationClosure, It as AuthErrorStatus, J as OrganizationTeam, K as OrganizationPage, L as OrganizationClosureCancelInput, Lt as UserApiCredential, M as EnterpriseConnectionSetup, Mt as UpdateProfileInput, N as FinuevaAuthClient, Nt as WorkspaceSelection, O as DriveCredential, Ot as TwoFactorStepUpInput, P as InvitationAcceptance, Pt as AuthError, Q as OrganizationWorkspaceSelection, R as OrganizationClosureStartInput, Rt as UserApiCredentialInput, S as CreatedOrganizationMemberInvitation, St as SocialIdTokenProvider, T as DeletedOrganizationTeam, Tt as SuspendedOrganizationMemberStatus, U as OrganizationMember, V as OrganizationInvitation, W as OrganizationMemberAuthority, X as OrganizationTeamMemberPage, Y as OrganizationTeamDisplay, Z as OrganizationTeamPage, _ as ClosingOrganization, _t as ScimCredentialIssuance, a as AuthPersistence, at as PlatformRoleApproval, b as CreateOrganizationMemberInvitationInput, bt as SignInInput, c as AuthSessionInventory, ct as PlatformStatus, d as AuthUser, dt as RecentAuthenticationStatus, et as PasskeySummary, f as CanceledOrganizationInvitation, ft as RemovedOrganizationMember, g as CeremonyReturnInput, gt as RotateScimCredentialInput, h as CeremonyRecentAuthenticationRequest, ht as RestoredOrganizationMember, i as AuthOrganization, it as PlatformRoleApplied, j as EnterpriseConnectionAction, jt as UpdateOrganizationTeamDisplayInput, k as DriveCredentialInput, kt as UpdateEnterpriseConnectionInput, l as AuthSessionSummary, lt as ReceivedOrganizationInvitation, m as CeremonyHandoffInput, mt as ResentOrganizationInvitation, n as AddedOrganizationTeamMember, nt as PlatformBootstrapRoleChangeInput, o as AuthPersistenceDriver, ot as PlatformRoleChangeRecentAuthenticationInput, p as CeremonyHandoff, pt as RemovedOrganizationTeamMember, q as OrganizationPageInput, r as AuthClientOptions, rt as PlatformRole, s as AuthSession, st as PlatformRoleFirstApproval, t as AcceptInvitationInput, tt as PersonalWorkspaceSelection, u as AuthState, ut as ReceivedOrganizationInvitationPage, v as ClosingOrganizationList, vt as ScimCredentialState, w as DeclineInvitationInput, wt as SuspendedOrganizationMemberPage, x as CreatedOrganization, xt as SocialIdTokenInput, y as CreateEnterpriseConnectionInput, yt as SendVerificationEmailInput, z as OrganizationDeparture } from "./types-sJ_vACZ3.js";
|
|
2
2
|
//#region src/client.d.ts
|
|
3
3
|
declare function createAuthClient(options: AuthClientOptions): FinuevaAuthClient;
|
|
4
4
|
//#endregion
|
|
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 };
|
|
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 CreateEnterpriseConnectionInput, type CreateOrganizationMemberInvitationInput, type CreatedOrganization, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DeclineInvitationInput, type DeletedOrganizationTeam, type DepartedOrganizationMember, type DepartedOrganizationMemberPage, type DriveCredential, type DriveCredentialInput, type EnterpriseConnection, type EnterpriseConnectionAction, type EnterpriseConnectionSetup, 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 UpdateEnterpriseConnectionInput, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UpdateProfileInput, type UserApiCredential, type UserApiCredentialInput, type WorkspaceSelection, createAuthClient };
|
package/dist/index.js
CHANGED
|
@@ -2537,6 +2537,12 @@ const messages = {
|
|
|
2537
2537
|
invalid_credentials: "The credentials are invalid.",
|
|
2538
2538
|
invalid_auth_input: "The authentication input is invalid.",
|
|
2539
2539
|
account_conflict: "The account is not available.",
|
|
2540
|
+
social_signup_required: "No account is available for this social sign-in. Start sign-up to create one.",
|
|
2541
|
+
google_recovery_in_progress: "A Google connection is already being completed. Return to that sign-in, or wait up to ten minutes and restart.",
|
|
2542
|
+
google_recovery_not_required: "Google account recovery is not required.",
|
|
2543
|
+
google_recovery_invalid: "The Google account recovery request is invalid.",
|
|
2544
|
+
google_recovery_expired: "Google account recovery has expired. Start Google sign-in again.",
|
|
2545
|
+
google_recovery_account_mismatch: "Sign in to the existing account associated with this Google identity.",
|
|
2540
2546
|
password_reset_invalid: "The password reset request is invalid.",
|
|
2541
2547
|
authentication_required: "Authentication is required.",
|
|
2542
2548
|
request_origin_denied: "The request origin is not allowed.",
|
|
@@ -2552,6 +2558,7 @@ const messages = {
|
|
|
2552
2558
|
organization_context_too_large: "The organization context is too large.",
|
|
2553
2559
|
credential_rate_limited: "Credential requests are temporarily limited.",
|
|
2554
2560
|
auth_request_rate_limited: "Authentication requests are temporarily limited.",
|
|
2561
|
+
organization_slug_unavailable: "The organization address is unavailable.",
|
|
2555
2562
|
state_conflict: "The authentication state conflicts with the request.",
|
|
2556
2563
|
access_denied: "Access is denied.",
|
|
2557
2564
|
platform_target_unavailable: "The platform administration target is unavailable.",
|
|
@@ -3429,7 +3436,12 @@ function fromAccountAuthorityError(value, status, retryAfter) {
|
|
|
3429
3436
|
function fromSocialIdTokenAuthorityError(value, status, retryAfter) {
|
|
3430
3437
|
const code = isObject(value) && typeof value.code === "string" ? value.code : void 0;
|
|
3431
3438
|
if (code === "INVALID_TOKEN" || code === "FAILED_TO_GET_USER_INFO" || code === "USER_EMAIL_NOT_FOUND") return new AuthError("invalid_credentials", 401);
|
|
3432
|
-
if (code === "OAUTH_LINK_ERROR")
|
|
3439
|
+
if (code === "OAUTH_LINK_ERROR") {
|
|
3440
|
+
const message = isObject(value) && typeof value.message === "string" ? value.message : void 0;
|
|
3441
|
+
if (message === "account not linked") return new AuthError("account_conflict", 409);
|
|
3442
|
+
if (message === "signup disabled") return new AuthError("social_signup_required", 409);
|
|
3443
|
+
return authorityUnavailable();
|
|
3444
|
+
}
|
|
3433
3445
|
return fromAccountAuthorityError(value, status, retryAfter);
|
|
3434
3446
|
}
|
|
3435
3447
|
function authorityUnavailable() {
|
|
@@ -3448,6 +3460,7 @@ function fromOrganizationReadAuthorityError(value, status) {
|
|
|
3448
3460
|
}
|
|
3449
3461
|
function fromOrganizationMutationAuthorityError(value, status, retryAfter) {
|
|
3450
3462
|
if (status === 400 || status === 413 || status === 415) return new AuthError("invalid_request", 400);
|
|
3463
|
+
if (status === 409 && isObject(value) && value.code === "ORGANIZATION_SLUG_UNAVAILABLE") return new AuthError("organization_slug_unavailable", 409);
|
|
3451
3464
|
if (status === 409) return new AuthError("state_conflict", 409);
|
|
3452
3465
|
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
3453
3466
|
const code = isObject(value) && typeof value.code === "string" ? value.code : void 0;
|
|
@@ -5078,6 +5091,75 @@ function fromEnterpriseAdministrationError(value, status, retryAfter) {
|
|
|
5078
5091
|
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
5079
5092
|
return authorityUnavailable();
|
|
5080
5093
|
}
|
|
5094
|
+
const setupKeys = [
|
|
5095
|
+
"id",
|
|
5096
|
+
"revision",
|
|
5097
|
+
"issuer",
|
|
5098
|
+
"clientId",
|
|
5099
|
+
"enabled",
|
|
5100
|
+
"memberJit",
|
|
5101
|
+
"domain",
|
|
5102
|
+
"domainVerified",
|
|
5103
|
+
"validatedAt",
|
|
5104
|
+
"testedAt",
|
|
5105
|
+
"dnsRecordName",
|
|
5106
|
+
"dnsRecordValue",
|
|
5107
|
+
"challengeExpiresAt",
|
|
5108
|
+
"redirectUri"
|
|
5109
|
+
];
|
|
5110
|
+
function normalizeEnterpriseConnectionSetup(value) {
|
|
5111
|
+
if (!exact(value, setupKeys) || typeof value.id !== "string" || !idPattern.test(value.id) || typeof value.issuer !== "string" || value.issuer.length > 2048 || !value.issuer.startsWith("https://") || typeof value.clientId !== "string" || value.clientId.length < 1 || value.clientId.length > 256 || typeof value.domain !== "string" || !/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/.test(value.domain) || value.domain.length > 253 || value.dnsRecordName !== `_finueva-sso.${value.domain}` || typeof value.dnsRecordValue !== "string" || !/^finueva-sso=[A-Za-z0-9_-]{43}$/.test(value.dnsRecordValue) || typeof value.redirectUri !== "string" || value.redirectUri.length > 2048 || !Number.isSafeInteger(value.revision) || value.revision < 0) throw authorityUnavailable();
|
|
5112
|
+
let redirect;
|
|
5113
|
+
try {
|
|
5114
|
+
redirect = new URL(value.redirectUri);
|
|
5115
|
+
} catch {
|
|
5116
|
+
throw authorityUnavailable();
|
|
5117
|
+
}
|
|
5118
|
+
if (redirect.protocol !== "https:" || redirect.username || redirect.password || redirect.search || redirect.hash || !redirect.pathname.endsWith(`/enterprise/callback/${value.id}`)) throw authorityUnavailable();
|
|
5119
|
+
return {
|
|
5120
|
+
id: value.id,
|
|
5121
|
+
revision: value.revision,
|
|
5122
|
+
issuer: value.issuer,
|
|
5123
|
+
clientId: value.clientId,
|
|
5124
|
+
enabled: bool(value.enabled),
|
|
5125
|
+
memberJit: bool(value.memberJit),
|
|
5126
|
+
domain: value.domain,
|
|
5127
|
+
domainVerified: bool(value.domainVerified),
|
|
5128
|
+
validatedAt: date(value.validatedAt, true),
|
|
5129
|
+
testedAt: date(value.testedAt, true),
|
|
5130
|
+
dnsRecordName: value.dnsRecordName,
|
|
5131
|
+
dnsRecordValue: value.dnsRecordValue,
|
|
5132
|
+
challengeExpiresAt: date(value.challengeExpiresAt, false),
|
|
5133
|
+
redirectUri: value.redirectUri
|
|
5134
|
+
};
|
|
5135
|
+
}
|
|
5136
|
+
function normalizeEnterpriseConnectionSetups(value) {
|
|
5137
|
+
if (!exact(value, ["connections"]) || !Array.isArray(value.connections) || value.connections.length > 10) throw authorityUnavailable();
|
|
5138
|
+
return value.connections.map(normalizeEnterpriseConnectionSetup);
|
|
5139
|
+
}
|
|
5140
|
+
function normalizeEnterpriseConnectionAction(value) {
|
|
5141
|
+
if (exact(value, ["removed"]) && value.removed === true) return { removed: true };
|
|
5142
|
+
return normalizeEnterpriseConnectionSetup(value);
|
|
5143
|
+
}
|
|
5144
|
+
function enterpriseInputString(value, max) {
|
|
5145
|
+
if (typeof value !== "string" || value.length < 1 || value.length > max) throw new TypeError("Enterprise configuration is invalid");
|
|
5146
|
+
return value;
|
|
5147
|
+
}
|
|
5148
|
+
function enterpriseInputBoolean(value) {
|
|
5149
|
+
if (typeof value !== "boolean") throw new TypeError("Enterprise configuration is invalid");
|
|
5150
|
+
return value;
|
|
5151
|
+
}
|
|
5152
|
+
function normalizeEnterpriseTestAuthorization(value) {
|
|
5153
|
+
if (!exact(value, ["url"]) || typeof value.url !== "string" || value.url.length > 16384) throw authorityUnavailable();
|
|
5154
|
+
let url;
|
|
5155
|
+
try {
|
|
5156
|
+
url = new URL(value.url);
|
|
5157
|
+
} catch {
|
|
5158
|
+
throw authorityUnavailable();
|
|
5159
|
+
}
|
|
5160
|
+
if (url.protocol !== "https:" || url.username || url.password || url.hash || !url.searchParams.get("state") || url.searchParams.get("response_type") !== "code") throw authorityUnavailable();
|
|
5161
|
+
return { url: value.url };
|
|
5162
|
+
}
|
|
5081
5163
|
//#endregion
|
|
5082
5164
|
//#region src/user-api/credential.ts
|
|
5083
5165
|
function userApiApplication(input) {
|
|
@@ -6079,6 +6161,65 @@ function createAuthClient(options) {
|
|
|
6079
6161
|
async listEnterpriseConnections(organizationId) {
|
|
6080
6162
|
return enterpriseRequest("GET", `${normalizeIdInput(organizationId)}/connections`, void 0, normalizeEnterpriseConnections);
|
|
6081
6163
|
},
|
|
6164
|
+
async startEnterpriseConnectionTest(organizationId, connectionId, input) {
|
|
6165
|
+
if (signOutRequest || activeAccountMutationGeneration !== void 0 || invitationRequest) throw new AuthError("state_conflict", 409);
|
|
6166
|
+
const generation = authorityGeneration;
|
|
6167
|
+
const value = await requestJson(joinURL(authOrigin, "api/v1/auth/enterprise/test-sign-in"), {
|
|
6168
|
+
fetch: fetchImpl,
|
|
6169
|
+
timeoutMs,
|
|
6170
|
+
method: "POST",
|
|
6171
|
+
headers: { "content-type": "application/json" },
|
|
6172
|
+
body: {
|
|
6173
|
+
organizationId: normalizeIdInput(organizationId),
|
|
6174
|
+
connectionId: normalizeIdInput(connectionId),
|
|
6175
|
+
expectedRevision: normalizeRevision(input?.expectedRevision),
|
|
6176
|
+
applicationId: normalizeIdInput(input?.applicationId),
|
|
6177
|
+
returnTo: enterpriseInputString(input?.returnTo, 2048)
|
|
6178
|
+
},
|
|
6179
|
+
mapError: fromEnterpriseAdministrationError
|
|
6180
|
+
});
|
|
6181
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
6182
|
+
return normalizeEnterpriseTestAuthorization(value);
|
|
6183
|
+
},
|
|
6184
|
+
async listEnterpriseConnectionSetups(organizationId) {
|
|
6185
|
+
return enterpriseRequest("GET", `${normalizeIdInput(organizationId)}/connection-setup`, void 0, normalizeEnterpriseConnectionSetups);
|
|
6186
|
+
},
|
|
6187
|
+
async createEnterpriseConnection(organizationId, input) {
|
|
6188
|
+
const body = {
|
|
6189
|
+
requestId: enterpriseInputString(input?.requestId, 36),
|
|
6190
|
+
issuer: enterpriseInputString(input?.issuer, 2048),
|
|
6191
|
+
clientId: enterpriseInputString(input?.clientId, 256),
|
|
6192
|
+
clientSecret: enterpriseInputString(input?.clientSecret, 512),
|
|
6193
|
+
domain: enterpriseInputString(input?.domain, 253),
|
|
6194
|
+
memberJit: enterpriseInputBoolean(input?.memberJit)
|
|
6195
|
+
};
|
|
6196
|
+
return enterpriseRequest("POST", `${normalizeIdInput(organizationId)}/connection-setup`, body, normalizeEnterpriseConnectionSetup);
|
|
6197
|
+
},
|
|
6198
|
+
async updateEnterpriseConnection(organizationId, connectionId, input) {
|
|
6199
|
+
const body = {
|
|
6200
|
+
expectedRevision: normalizeRevision(input?.expectedRevision),
|
|
6201
|
+
issuer: enterpriseInputString(input?.issuer, 2048),
|
|
6202
|
+
clientId: enterpriseInputString(input?.clientId, 256),
|
|
6203
|
+
memberJit: enterpriseInputBoolean(input?.memberJit),
|
|
6204
|
+
...input?.clientSecret === void 0 ? {} : { clientSecret: enterpriseInputString(input.clientSecret, 512) }
|
|
6205
|
+
};
|
|
6206
|
+
return enterpriseRequest("POST", `${normalizeIdInput(organizationId)}/connection-setup/${normalizeIdInput(connectionId)}`, body, normalizeEnterpriseConnectionSetup);
|
|
6207
|
+
},
|
|
6208
|
+
async actOnEnterpriseConnection(organizationId, connectionId, input) {
|
|
6209
|
+
if (![
|
|
6210
|
+
"challenge",
|
|
6211
|
+
"verify",
|
|
6212
|
+
"validate",
|
|
6213
|
+
"enable",
|
|
6214
|
+
"disable",
|
|
6215
|
+
"archive"
|
|
6216
|
+
].includes(input?.action)) throw new TypeError("Enterprise action is invalid");
|
|
6217
|
+
const body = {
|
|
6218
|
+
expectedRevision: normalizeRevision(input?.expectedRevision),
|
|
6219
|
+
action: input.action
|
|
6220
|
+
};
|
|
6221
|
+
return enterpriseRequest("POST", `${normalizeIdInput(organizationId)}/connection-setup/${normalizeIdInput(connectionId)}/actions`, body, normalizeEnterpriseConnectionAction);
|
|
6222
|
+
},
|
|
6082
6223
|
async getScimCredential(organizationId, connectionId) {
|
|
6083
6224
|
return enterpriseRequest("GET", scimCredentialPath(organizationId, connectionId), void 0, (value) => normalizeScimCredentialState(value));
|
|
6084
6225
|
},
|
package/dist/server.d.ts
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
import { At as
|
|
1
|
+
import { At as UpdateOrganizationDisplayInput, B as OrganizationDisplay, C as CreatedOrganizationTeam, F as InvitationDecline, Ft as AuthErrorCode, G as OrganizationMemberPage, H as OrganizationInvitationPage, It as AuthErrorStatus, J as OrganizationTeam, K as OrganizationPage, Lt as UserApiCredential, Nt as WorkspaceSelection, O as DriveCredential, P as InvitationAcceptance, Pt as AuthError, Q as OrganizationWorkspaceSelection, Rt as UserApiCredentialInput, S as CreatedOrganizationMemberInvitation, St as SocialIdTokenProvider, T as DeletedOrganizationTeam, U as OrganizationMember, V as OrganizationInvitation, W as OrganizationMemberAuthority, X as OrganizationTeamMemberPage, Y as OrganizationTeamDisplay, Z as OrganizationTeamPage, b as CreateOrganizationMemberInvitationInput, d as AuthUser, f as CanceledOrganizationInvitation, ft as RemovedOrganizationMember, i as AuthOrganization, jt as UpdateOrganizationTeamDisplayInput, k as DriveCredentialInput, lt as ReceivedOrganizationInvitation, mt as ResentOrganizationInvitation, n as AddedOrganizationTeamMember, pt as RemovedOrganizationTeamMember, q as OrganizationPageInput, s as AuthSession, t as AcceptInvitationInput, tt as PersonalWorkspaceSelection, ut as ReceivedOrganizationInvitationPage, w as DeclineInvitationInput, x as CreatedOrganization, xt as SocialIdTokenInput, z as OrganizationDeparture } from "./types-sJ_vACZ3.js";
|
|
2
|
+
//#region src/google-recovery.d.ts
|
|
3
|
+
interface GoogleAccountRecoveryInput {
|
|
4
|
+
idToken: {
|
|
5
|
+
token: string;
|
|
6
|
+
nonce?: string;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
interface CompleteGoogleAccountRecoveryInput extends GoogleAccountRecoveryInput {
|
|
10
|
+
recoveryToken: string;
|
|
11
|
+
}
|
|
12
|
+
interface GoogleAccountRecovery {
|
|
13
|
+
recoveryToken: string;
|
|
14
|
+
expiresAt: string;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
2
17
|
//#region src/user-api/verifier.d.ts
|
|
3
18
|
interface UserApiIdentity {
|
|
4
19
|
userId: string;
|
|
@@ -150,10 +165,14 @@ interface FinuevaServerAuth {
|
|
|
150
165
|
listReceivedInvitations(input?: OrganizationPageInput): Promise<ReceivedOrganizationInvitationPage>;
|
|
151
166
|
getReceivedInvitation(invitationId: string): Promise<ReceivedOrganizationInvitation>;
|
|
152
167
|
signInWithSocialIdToken(input: SocialIdTokenInput): Promise<ServerSocialIdTokenSession>;
|
|
168
|
+
startGoogleAccountRecovery(input: GoogleAccountRecoveryInput): Promise<GoogleAccountRecovery>;
|
|
169
|
+
completeGoogleAccountRecovery(input: CompleteGoogleAccountRecoveryInput): Promise<{
|
|
170
|
+
linked: true;
|
|
171
|
+
}>;
|
|
153
172
|
getDriveCredential(input: DriveCredentialInput): Promise<DriveCredential>;
|
|
154
173
|
getUserApiCredential(input: UserApiCredentialInput): Promise<UserApiCredential>;
|
|
155
174
|
signOut(): Promise<ServerSignOutResult>;
|
|
156
175
|
}
|
|
157
176
|
declare function createServerAuth(options: ServerAuthOptions): FinuevaServerAuth;
|
|
158
177
|
//#endregion
|
|
159
|
-
export { type AcceptInvitationInput, type AddedOrganizationTeamMember, AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type AuthSession, type AuthUser, type CanceledOrganizationInvitation, type CreateOrganizationMemberInvitationInput, type CreatedOrganization, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DeclineInvitationInput, type DeletedOrganizationTeam, type DriveCredential, type DriveCredentialInput, type DriveProvisioningAuthOptions, type DriveProvisioningCredential, type DriveRecipient, type DriveRecipientAuthOptions, type FinuevaDriveProvisioningAuth, type FinuevaDriveRecipientAuth, type FinuevaIdentityResolverAuth, type FinuevaMembershipResolverAuth, FinuevaServerAuth, type IdentityResolverAuthOptions, type InvitationAcceptance, type InvitationDecline, type MembershipResolverAuthOptions, 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 ReceivedOrganizationInvitation, type ReceivedOrganizationInvitationPage, type RemovedOrganizationMember, type RemovedOrganizationTeamMember, type ResentOrganizationInvitation, type ResolveDriveRecipientInput, type ResolveIdentityInput, type ResolveMembershipInput, type ResolvedIdentity, type ResolvedMembership, type ResolvedMembershipRole, ServerAuthOptions, ServerInvitationAcceptance, ServerSignOutResult, ServerSocialIdTokenSession, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UserApiCredential, type UserApiCredentialInput, type UserApiIdentity, type UserApiVerifierOptions, type WorkspaceSelection, createDriveProvisioningAuth, createDriveRecipientAuth, createIdentityResolverAuth, createMembershipResolverAuth, createServerAuth, createUserApiVerifier };
|
|
178
|
+
export { type AcceptInvitationInput, type AddedOrganizationTeamMember, AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type AuthSession, type AuthUser, type CanceledOrganizationInvitation, type CompleteGoogleAccountRecoveryInput, type CreateOrganizationMemberInvitationInput, type CreatedOrganization, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DeclineInvitationInput, type DeletedOrganizationTeam, type DriveCredential, type DriveCredentialInput, type DriveProvisioningAuthOptions, type DriveProvisioningCredential, type DriveRecipient, type DriveRecipientAuthOptions, type FinuevaDriveProvisioningAuth, type FinuevaDriveRecipientAuth, type FinuevaIdentityResolverAuth, type FinuevaMembershipResolverAuth, FinuevaServerAuth, type GoogleAccountRecovery, type GoogleAccountRecoveryInput, type IdentityResolverAuthOptions, type InvitationAcceptance, type InvitationDecline, type MembershipResolverAuthOptions, 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 ReceivedOrganizationInvitation, type ReceivedOrganizationInvitationPage, type RemovedOrganizationMember, type RemovedOrganizationTeamMember, type ResentOrganizationInvitation, type ResolveDriveRecipientInput, type ResolveIdentityInput, type ResolveMembershipInput, type ResolvedIdentity, type ResolvedMembership, type ResolvedMembershipRole, ServerAuthOptions, ServerInvitationAcceptance, ServerSignOutResult, ServerSocialIdTokenSession, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UserApiCredential, type UserApiCredentialInput, type UserApiIdentity, type UserApiVerifierOptions, type WorkspaceSelection, createDriveProvisioningAuth, createDriveRecipientAuth, createIdentityResolverAuth, createMembershipResolverAuth, createServerAuth, createUserApiVerifier };
|
package/dist/server.js
CHANGED
|
@@ -1,183 +1,14 @@
|
|
|
1
|
-
String.fromCharCode;
|
|
2
|
-
const HASH_RE = /#/g;
|
|
3
|
-
const AMPERSAND_RE = /&/g;
|
|
4
|
-
const SLASH_RE = /\//g;
|
|
5
|
-
const EQUAL_RE = /=/g;
|
|
6
|
-
const PLUS_RE = /\+/g;
|
|
7
|
-
const ENC_CARET_RE = /%5e/gi;
|
|
8
|
-
const ENC_BACKTICK_RE = /%60/gi;
|
|
9
|
-
const ENC_PIPE_RE = /%7c/gi;
|
|
10
|
-
const ENC_SPACE_RE = /%20/gi;
|
|
11
|
-
function encode$2(text) {
|
|
12
|
-
return encodeURI("" + text).replace(ENC_PIPE_RE, "|");
|
|
13
|
-
}
|
|
14
|
-
function encodeQueryValue(input) {
|
|
15
|
-
return encode$2(typeof input === "string" ? input : JSON.stringify(input)).replace(PLUS_RE, "%2B").replace(ENC_SPACE_RE, "+").replace(HASH_RE, "%23").replace(AMPERSAND_RE, "%26").replace(ENC_BACKTICK_RE, "`").replace(ENC_CARET_RE, "^").replace(SLASH_RE, "%2F");
|
|
16
|
-
}
|
|
17
|
-
function encodeQueryKey(text) {
|
|
18
|
-
return encodeQueryValue(text).replace(EQUAL_RE, "%3D");
|
|
19
|
-
}
|
|
20
|
-
function decode$1(text = "") {
|
|
21
|
-
try {
|
|
22
|
-
return decodeURIComponent("" + text);
|
|
23
|
-
} catch {
|
|
24
|
-
return "" + text;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function decodeQueryKey(text) {
|
|
28
|
-
return decode$1(text.replace(PLUS_RE, " "));
|
|
29
|
-
}
|
|
30
|
-
function decodeQueryValue(text) {
|
|
31
|
-
return decode$1(text.replace(PLUS_RE, " "));
|
|
32
|
-
}
|
|
33
|
-
function parseQuery(parametersString = "") {
|
|
34
|
-
const object = Object.create(null);
|
|
35
|
-
if (parametersString[0] === "?") parametersString = parametersString.slice(1);
|
|
36
|
-
for (const parameter of parametersString.split("&")) {
|
|
37
|
-
const s = parameter.match(/([^=]+)=?(.*)/) || [];
|
|
38
|
-
if (s.length < 2) continue;
|
|
39
|
-
const key = decodeQueryKey(s[1]);
|
|
40
|
-
if (key === "__proto__" || key === "constructor") continue;
|
|
41
|
-
const value = decodeQueryValue(s[2] || "");
|
|
42
|
-
if (object[key] === void 0) object[key] = value;
|
|
43
|
-
else if (Array.isArray(object[key])) object[key].push(value);
|
|
44
|
-
else object[key] = [object[key], value];
|
|
45
|
-
}
|
|
46
|
-
return object;
|
|
47
|
-
}
|
|
48
|
-
function encodeQueryItem(key, value) {
|
|
49
|
-
if (typeof value === "number" || typeof value === "boolean") value = String(value);
|
|
50
|
-
if (!value) return encodeQueryKey(key);
|
|
51
|
-
if (Array.isArray(value)) return value.map((_value) => `${encodeQueryKey(key)}=${encodeQueryValue(_value)}`).join("&");
|
|
52
|
-
return `${encodeQueryKey(key)}=${encodeQueryValue(value)}`;
|
|
53
|
-
}
|
|
54
|
-
function stringifyQuery(query) {
|
|
55
|
-
return Object.keys(query).filter((k) => query[k] !== void 0).map((k) => encodeQueryItem(k, query[k])).filter(Boolean).join("&");
|
|
56
|
-
}
|
|
57
|
-
const PROTOCOL_STRICT_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{1,2})/;
|
|
58
|
-
const PROTOCOL_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{2})?/;
|
|
59
|
-
const PROTOCOL_RELATIVE_REGEX = /^([/\\]\s*){2,}[^/\\]/;
|
|
60
|
-
const TRAILING_SLASH_RE = /\/$|\/\?|\/#/;
|
|
61
|
-
const JOIN_LEADING_SLASH_RE = /^\.?\//;
|
|
62
|
-
function hasProtocol(inputString, opts = {}) {
|
|
63
|
-
if (typeof opts === "boolean") opts = { acceptRelative: opts };
|
|
64
|
-
if (opts.strict) return PROTOCOL_STRICT_REGEX.test(inputString);
|
|
65
|
-
return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);
|
|
66
|
-
}
|
|
67
|
-
function hasTrailingSlash(input = "", respectQueryAndFragment) {
|
|
68
|
-
if (!respectQueryAndFragment) return input.endsWith("/");
|
|
69
|
-
return TRAILING_SLASH_RE.test(input);
|
|
70
|
-
}
|
|
71
|
-
function withoutTrailingSlash(input = "", respectQueryAndFragment) {
|
|
72
|
-
if (!respectQueryAndFragment) return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
|
|
73
|
-
if (!hasTrailingSlash(input, true)) return input || "/";
|
|
74
|
-
let path = input;
|
|
75
|
-
let fragment = "";
|
|
76
|
-
const fragmentIndex = input.indexOf("#");
|
|
77
|
-
if (fragmentIndex !== -1) {
|
|
78
|
-
path = input.slice(0, fragmentIndex);
|
|
79
|
-
fragment = input.slice(fragmentIndex);
|
|
80
|
-
}
|
|
81
|
-
const [s0, ...s] = path.split("?");
|
|
82
|
-
return ((s0.endsWith("/") ? s0.slice(0, -1) : s0) || "/") + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
|
|
83
|
-
}
|
|
84
|
-
function withTrailingSlash(input = "", respectQueryAndFragment) {
|
|
85
|
-
if (!respectQueryAndFragment) return input.endsWith("/") ? input : input + "/";
|
|
86
|
-
if (hasTrailingSlash(input, true)) return input || "/";
|
|
87
|
-
let path = input;
|
|
88
|
-
let fragment = "";
|
|
89
|
-
const fragmentIndex = input.indexOf("#");
|
|
90
|
-
if (fragmentIndex !== -1) {
|
|
91
|
-
path = input.slice(0, fragmentIndex);
|
|
92
|
-
fragment = input.slice(fragmentIndex);
|
|
93
|
-
if (!path) return fragment;
|
|
94
|
-
}
|
|
95
|
-
const [s0, ...s] = path.split("?");
|
|
96
|
-
return s0 + "/" + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
|
|
97
|
-
}
|
|
98
|
-
function withBase(input, base) {
|
|
99
|
-
if (isEmptyURL(base) || hasProtocol(input)) return input;
|
|
100
|
-
const _base = withoutTrailingSlash(base);
|
|
101
|
-
if (input.startsWith(_base)) {
|
|
102
|
-
const nextChar = input[_base.length];
|
|
103
|
-
if (!nextChar || nextChar === "/" || nextChar === "?") return input;
|
|
104
|
-
}
|
|
105
|
-
return joinURL(_base, input);
|
|
106
|
-
}
|
|
107
|
-
function withQuery(input, query) {
|
|
108
|
-
const parsed = parseURL(input);
|
|
109
|
-
parsed.search = stringifyQuery({
|
|
110
|
-
...parseQuery(parsed.search),
|
|
111
|
-
...query
|
|
112
|
-
});
|
|
113
|
-
return stringifyParsedURL(parsed);
|
|
114
|
-
}
|
|
115
|
-
function isEmptyURL(url) {
|
|
116
|
-
return !url || url === "/";
|
|
117
|
-
}
|
|
118
|
-
function isNonEmptyURL(url) {
|
|
119
|
-
return url && url !== "/";
|
|
120
|
-
}
|
|
121
|
-
function joinURL(base, ...input) {
|
|
122
|
-
let url = base || "";
|
|
123
|
-
for (const segment of input.filter((url2) => isNonEmptyURL(url2))) if (url) {
|
|
124
|
-
const _segment = segment.replace(JOIN_LEADING_SLASH_RE, "");
|
|
125
|
-
url = withTrailingSlash(url) + _segment;
|
|
126
|
-
} else url = segment;
|
|
127
|
-
return url;
|
|
128
|
-
}
|
|
129
|
-
const protocolRelative = Symbol.for("ufo:protocolRelative");
|
|
130
|
-
function parseURL(input = "", defaultProto) {
|
|
131
|
-
const _specialProtoMatch = input.match(/^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i);
|
|
132
|
-
if (_specialProtoMatch) {
|
|
133
|
-
const [, _proto, _pathname = ""] = _specialProtoMatch;
|
|
134
|
-
return {
|
|
135
|
-
protocol: _proto.toLowerCase(),
|
|
136
|
-
pathname: _pathname,
|
|
137
|
-
href: _proto + _pathname,
|
|
138
|
-
auth: "",
|
|
139
|
-
host: "",
|
|
140
|
-
search: "",
|
|
141
|
-
hash: ""
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
if (!hasProtocol(input, { acceptRelative: true })) return defaultProto ? parseURL(defaultProto + input) : parsePath(input);
|
|
145
|
-
const [, protocol = "", auth, hostAndPath = ""] = input.replace(/\\/g, "/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/) || [];
|
|
146
|
-
let [, host = "", path = ""] = hostAndPath.match(/([^#/?]*)(.*)?/) || [];
|
|
147
|
-
if (protocol === "file:") path = path.replace(/\/(?=[A-Za-z]:)/, "");
|
|
148
|
-
const { pathname, search, hash } = parsePath(path);
|
|
149
|
-
return {
|
|
150
|
-
protocol: protocol.toLowerCase(),
|
|
151
|
-
auth: auth ? auth.slice(0, Math.max(0, auth.length - 1)) : "",
|
|
152
|
-
host,
|
|
153
|
-
pathname,
|
|
154
|
-
search,
|
|
155
|
-
hash,
|
|
156
|
-
[protocolRelative]: !protocol
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
function parsePath(input = "") {
|
|
160
|
-
const [pathname = "", search = "", hash = ""] = (input.match(/([^#?]*)(\?[^#]*)?(#.*)?/) || []).splice(1);
|
|
161
|
-
return {
|
|
162
|
-
pathname,
|
|
163
|
-
search,
|
|
164
|
-
hash
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
function stringifyParsedURL(parsed) {
|
|
168
|
-
const pathname = parsed.pathname || "";
|
|
169
|
-
const search = parsed.search ? (parsed.search.startsWith("?") ? "" : "?") + parsed.search : "";
|
|
170
|
-
const hash = parsed.hash || "";
|
|
171
|
-
const auth = parsed.auth ? parsed.auth + "@" : "";
|
|
172
|
-
const host = parsed.host || "";
|
|
173
|
-
return (parsed.protocol || parsed[protocolRelative] ? (parsed.protocol || "") + "//" : "") + auth + host + pathname + search + hash;
|
|
174
|
-
}
|
|
175
|
-
//#endregion
|
|
176
1
|
//#region src/errors.ts
|
|
177
2
|
const messages = {
|
|
178
3
|
invalid_credentials: "The credentials are invalid.",
|
|
179
4
|
invalid_auth_input: "The authentication input is invalid.",
|
|
180
5
|
account_conflict: "The account is not available.",
|
|
6
|
+
social_signup_required: "No account is available for this social sign-in. Start sign-up to create one.",
|
|
7
|
+
google_recovery_in_progress: "A Google connection is already being completed. Return to that sign-in, or wait up to ten minutes and restart.",
|
|
8
|
+
google_recovery_not_required: "Google account recovery is not required.",
|
|
9
|
+
google_recovery_invalid: "The Google account recovery request is invalid.",
|
|
10
|
+
google_recovery_expired: "Google account recovery has expired. Start Google sign-in again.",
|
|
11
|
+
google_recovery_account_mismatch: "Sign in to the existing account associated with this Google identity.",
|
|
181
12
|
password_reset_invalid: "The password reset request is invalid.",
|
|
182
13
|
authentication_required: "Authentication is required.",
|
|
183
14
|
request_origin_denied: "The request origin is not allowed.",
|
|
@@ -193,6 +24,7 @@ const messages = {
|
|
|
193
24
|
organization_context_too_large: "The organization context is too large.",
|
|
194
25
|
credential_rate_limited: "Credential requests are temporarily limited.",
|
|
195
26
|
auth_request_rate_limited: "Authentication requests are temporarily limited.",
|
|
27
|
+
organization_slug_unavailable: "The organization address is unavailable.",
|
|
196
28
|
state_conflict: "The authentication state conflicts with the request.",
|
|
197
29
|
access_denied: "Access is denied.",
|
|
198
30
|
platform_target_unavailable: "The platform administration target is unavailable.",
|
|
@@ -688,7 +520,12 @@ function fromAccountAuthorityError(value, status, retryAfter) {
|
|
|
688
520
|
function fromSocialIdTokenAuthorityError(value, status, retryAfter) {
|
|
689
521
|
const code = isObject$1(value) && typeof value.code === "string" ? value.code : void 0;
|
|
690
522
|
if (code === "INVALID_TOKEN" || code === "FAILED_TO_GET_USER_INFO" || code === "USER_EMAIL_NOT_FOUND") return new AuthError("invalid_credentials", 401);
|
|
691
|
-
if (code === "OAUTH_LINK_ERROR")
|
|
523
|
+
if (code === "OAUTH_LINK_ERROR") {
|
|
524
|
+
const message = isObject$1(value) && typeof value.message === "string" ? value.message : void 0;
|
|
525
|
+
if (message === "account not linked") return new AuthError("account_conflict", 409);
|
|
526
|
+
if (message === "signup disabled") return new AuthError("social_signup_required", 409);
|
|
527
|
+
return authorityUnavailable();
|
|
528
|
+
}
|
|
692
529
|
return fromAccountAuthorityError(value, status, retryAfter);
|
|
693
530
|
}
|
|
694
531
|
function authorityUnavailable() {
|
|
@@ -707,6 +544,7 @@ function fromOrganizationReadAuthorityError(value, status) {
|
|
|
707
544
|
}
|
|
708
545
|
function fromOrganizationMutationAuthorityError(value, status, retryAfter) {
|
|
709
546
|
if (status === 400 || status === 413 || status === 415) return new AuthError("invalid_request", 400);
|
|
547
|
+
if (status === 409 && isObject$1(value) && value.code === "ORGANIZATION_SLUG_UNAVAILABLE") return new AuthError("organization_slug_unavailable", 409);
|
|
710
548
|
if (status === 409) return new AuthError("state_conflict", 409);
|
|
711
549
|
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
712
550
|
const code = isObject$1(value) && typeof value.code === "string" ? value.code : void 0;
|
|
@@ -877,6 +715,229 @@ function isObject$1(value) {
|
|
|
877
715
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
878
716
|
}
|
|
879
717
|
//#endregion
|
|
718
|
+
//#region src/google-recovery.ts
|
|
719
|
+
function object(value) {
|
|
720
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
721
|
+
}
|
|
722
|
+
function validTicket(value) {
|
|
723
|
+
return typeof value === "string" && /^[A-Za-z0-9_-]{43}$/.test(value);
|
|
724
|
+
}
|
|
725
|
+
function googleRecoveryInput(value, complete) {
|
|
726
|
+
if (!object(value) || Object.keys(value).sort().join(",") !== (complete ? "idToken,recoveryToken" : "idToken") || !object(value.idToken) || Object.keys(value.idToken).some((key) => key !== "token" && key !== "nonce") || complete && !validTicket(value.recoveryToken)) throw new AuthError("invalid_request", 400);
|
|
727
|
+
const social = normalizeSocialIdTokenInput({
|
|
728
|
+
provider: "google",
|
|
729
|
+
idToken: value.idToken.token,
|
|
730
|
+
signUp: false,
|
|
731
|
+
...value.idToken.nonce === void 0 ? {} : { nonce: value.idToken.nonce }
|
|
732
|
+
});
|
|
733
|
+
return {
|
|
734
|
+
idToken: {
|
|
735
|
+
token: social.idToken,
|
|
736
|
+
...social.nonce === void 0 ? {} : { nonce: social.nonce }
|
|
737
|
+
},
|
|
738
|
+
...complete ? { recoveryToken: value.recoveryToken } : {}
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
function normalizeGoogleRecovery(value, now) {
|
|
742
|
+
if (!object(value) || Object.keys(value).sort().join(",") !== "expiresAt,recoveryToken" || !validTicket(value.recoveryToken) || typeof value.expiresAt !== "string") throw authorityUnavailable();
|
|
743
|
+
const expiresAt = Date.parse(value.expiresAt);
|
|
744
|
+
if (!Number.isFinite(expiresAt) || expiresAt <= now || expiresAt > now + 10 * 6e4) throw authorityUnavailable();
|
|
745
|
+
return {
|
|
746
|
+
recoveryToken: value.recoveryToken,
|
|
747
|
+
expiresAt: value.expiresAt
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
function normalizeGoogleRecoveryCompletion(value) {
|
|
751
|
+
if (!object(value) || Object.keys(value).join(",") !== "linked" || value.linked !== true) throw authorityUnavailable();
|
|
752
|
+
return { linked: true };
|
|
753
|
+
}
|
|
754
|
+
function fromGoogleRecoveryError(value, status, retryAfter) {
|
|
755
|
+
const code = object(value) ? value.code : void 0;
|
|
756
|
+
if (status === 409 && code === "GOOGLE_RECOVERY_IN_PROGRESS") return new AuthError("google_recovery_in_progress", 409);
|
|
757
|
+
if (status === 409 && code === "GOOGLE_RECOVERY_NOT_REQUIRED") return new AuthError("google_recovery_not_required", 409);
|
|
758
|
+
if (status === 403 && code === "GOOGLE_RECOVERY_EMAIL_VERIFICATION_REQUIRED") return new AuthError("email_verification_required", 403);
|
|
759
|
+
if (status === 400 && code === "GOOGLE_RECOVERY_INVALID") return new AuthError("google_recovery_invalid", 400);
|
|
760
|
+
if (status === 410 && code === "GOOGLE_RECOVERY_EXPIRED") return new AuthError("google_recovery_expired", 410);
|
|
761
|
+
if (status === 403 && code === "GOOGLE_RECOVERY_ACCOUNT_MISMATCH") return new AuthError("google_recovery_account_mismatch", 403);
|
|
762
|
+
if (status === 401 && code === "GOOGLE_RECOVERY_FRESH_SIGN_IN_REQUIRED") return new AuthError("recent_sign_in_required", 401);
|
|
763
|
+
if (code === "GOOGLE_RECOVERY_UNAVAILABLE") return authorityUnavailable();
|
|
764
|
+
return fromAccountAuthorityError(value, status, retryAfter);
|
|
765
|
+
}
|
|
766
|
+
String.fromCharCode;
|
|
767
|
+
const HASH_RE = /#/g;
|
|
768
|
+
const AMPERSAND_RE = /&/g;
|
|
769
|
+
const SLASH_RE = /\//g;
|
|
770
|
+
const EQUAL_RE = /=/g;
|
|
771
|
+
const PLUS_RE = /\+/g;
|
|
772
|
+
const ENC_CARET_RE = /%5e/gi;
|
|
773
|
+
const ENC_BACKTICK_RE = /%60/gi;
|
|
774
|
+
const ENC_PIPE_RE = /%7c/gi;
|
|
775
|
+
const ENC_SPACE_RE = /%20/gi;
|
|
776
|
+
function encode$2(text) {
|
|
777
|
+
return encodeURI("" + text).replace(ENC_PIPE_RE, "|");
|
|
778
|
+
}
|
|
779
|
+
function encodeQueryValue(input) {
|
|
780
|
+
return encode$2(typeof input === "string" ? input : JSON.stringify(input)).replace(PLUS_RE, "%2B").replace(ENC_SPACE_RE, "+").replace(HASH_RE, "%23").replace(AMPERSAND_RE, "%26").replace(ENC_BACKTICK_RE, "`").replace(ENC_CARET_RE, "^").replace(SLASH_RE, "%2F");
|
|
781
|
+
}
|
|
782
|
+
function encodeQueryKey(text) {
|
|
783
|
+
return encodeQueryValue(text).replace(EQUAL_RE, "%3D");
|
|
784
|
+
}
|
|
785
|
+
function decode$1(text = "") {
|
|
786
|
+
try {
|
|
787
|
+
return decodeURIComponent("" + text);
|
|
788
|
+
} catch {
|
|
789
|
+
return "" + text;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
function decodeQueryKey(text) {
|
|
793
|
+
return decode$1(text.replace(PLUS_RE, " "));
|
|
794
|
+
}
|
|
795
|
+
function decodeQueryValue(text) {
|
|
796
|
+
return decode$1(text.replace(PLUS_RE, " "));
|
|
797
|
+
}
|
|
798
|
+
function parseQuery(parametersString = "") {
|
|
799
|
+
const object = Object.create(null);
|
|
800
|
+
if (parametersString[0] === "?") parametersString = parametersString.slice(1);
|
|
801
|
+
for (const parameter of parametersString.split("&")) {
|
|
802
|
+
const s = parameter.match(/([^=]+)=?(.*)/) || [];
|
|
803
|
+
if (s.length < 2) continue;
|
|
804
|
+
const key = decodeQueryKey(s[1]);
|
|
805
|
+
if (key === "__proto__" || key === "constructor") continue;
|
|
806
|
+
const value = decodeQueryValue(s[2] || "");
|
|
807
|
+
if (object[key] === void 0) object[key] = value;
|
|
808
|
+
else if (Array.isArray(object[key])) object[key].push(value);
|
|
809
|
+
else object[key] = [object[key], value];
|
|
810
|
+
}
|
|
811
|
+
return object;
|
|
812
|
+
}
|
|
813
|
+
function encodeQueryItem(key, value) {
|
|
814
|
+
if (typeof value === "number" || typeof value === "boolean") value = String(value);
|
|
815
|
+
if (!value) return encodeQueryKey(key);
|
|
816
|
+
if (Array.isArray(value)) return value.map((_value) => `${encodeQueryKey(key)}=${encodeQueryValue(_value)}`).join("&");
|
|
817
|
+
return `${encodeQueryKey(key)}=${encodeQueryValue(value)}`;
|
|
818
|
+
}
|
|
819
|
+
function stringifyQuery(query) {
|
|
820
|
+
return Object.keys(query).filter((k) => query[k] !== void 0).map((k) => encodeQueryItem(k, query[k])).filter(Boolean).join("&");
|
|
821
|
+
}
|
|
822
|
+
const PROTOCOL_STRICT_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{1,2})/;
|
|
823
|
+
const PROTOCOL_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{2})?/;
|
|
824
|
+
const PROTOCOL_RELATIVE_REGEX = /^([/\\]\s*){2,}[^/\\]/;
|
|
825
|
+
const TRAILING_SLASH_RE = /\/$|\/\?|\/#/;
|
|
826
|
+
const JOIN_LEADING_SLASH_RE = /^\.?\//;
|
|
827
|
+
function hasProtocol(inputString, opts = {}) {
|
|
828
|
+
if (typeof opts === "boolean") opts = { acceptRelative: opts };
|
|
829
|
+
if (opts.strict) return PROTOCOL_STRICT_REGEX.test(inputString);
|
|
830
|
+
return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);
|
|
831
|
+
}
|
|
832
|
+
function hasTrailingSlash(input = "", respectQueryAndFragment) {
|
|
833
|
+
if (!respectQueryAndFragment) return input.endsWith("/");
|
|
834
|
+
return TRAILING_SLASH_RE.test(input);
|
|
835
|
+
}
|
|
836
|
+
function withoutTrailingSlash(input = "", respectQueryAndFragment) {
|
|
837
|
+
if (!respectQueryAndFragment) return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
|
|
838
|
+
if (!hasTrailingSlash(input, true)) return input || "/";
|
|
839
|
+
let path = input;
|
|
840
|
+
let fragment = "";
|
|
841
|
+
const fragmentIndex = input.indexOf("#");
|
|
842
|
+
if (fragmentIndex !== -1) {
|
|
843
|
+
path = input.slice(0, fragmentIndex);
|
|
844
|
+
fragment = input.slice(fragmentIndex);
|
|
845
|
+
}
|
|
846
|
+
const [s0, ...s] = path.split("?");
|
|
847
|
+
return ((s0.endsWith("/") ? s0.slice(0, -1) : s0) || "/") + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
|
|
848
|
+
}
|
|
849
|
+
function withTrailingSlash(input = "", respectQueryAndFragment) {
|
|
850
|
+
if (!respectQueryAndFragment) return input.endsWith("/") ? input : input + "/";
|
|
851
|
+
if (hasTrailingSlash(input, true)) return input || "/";
|
|
852
|
+
let path = input;
|
|
853
|
+
let fragment = "";
|
|
854
|
+
const fragmentIndex = input.indexOf("#");
|
|
855
|
+
if (fragmentIndex !== -1) {
|
|
856
|
+
path = input.slice(0, fragmentIndex);
|
|
857
|
+
fragment = input.slice(fragmentIndex);
|
|
858
|
+
if (!path) return fragment;
|
|
859
|
+
}
|
|
860
|
+
const [s0, ...s] = path.split("?");
|
|
861
|
+
return s0 + "/" + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
|
|
862
|
+
}
|
|
863
|
+
function withBase(input, base) {
|
|
864
|
+
if (isEmptyURL(base) || hasProtocol(input)) return input;
|
|
865
|
+
const _base = withoutTrailingSlash(base);
|
|
866
|
+
if (input.startsWith(_base)) {
|
|
867
|
+
const nextChar = input[_base.length];
|
|
868
|
+
if (!nextChar || nextChar === "/" || nextChar === "?") return input;
|
|
869
|
+
}
|
|
870
|
+
return joinURL(_base, input);
|
|
871
|
+
}
|
|
872
|
+
function withQuery(input, query) {
|
|
873
|
+
const parsed = parseURL(input);
|
|
874
|
+
parsed.search = stringifyQuery({
|
|
875
|
+
...parseQuery(parsed.search),
|
|
876
|
+
...query
|
|
877
|
+
});
|
|
878
|
+
return stringifyParsedURL(parsed);
|
|
879
|
+
}
|
|
880
|
+
function isEmptyURL(url) {
|
|
881
|
+
return !url || url === "/";
|
|
882
|
+
}
|
|
883
|
+
function isNonEmptyURL(url) {
|
|
884
|
+
return url && url !== "/";
|
|
885
|
+
}
|
|
886
|
+
function joinURL(base, ...input) {
|
|
887
|
+
let url = base || "";
|
|
888
|
+
for (const segment of input.filter((url2) => isNonEmptyURL(url2))) if (url) {
|
|
889
|
+
const _segment = segment.replace(JOIN_LEADING_SLASH_RE, "");
|
|
890
|
+
url = withTrailingSlash(url) + _segment;
|
|
891
|
+
} else url = segment;
|
|
892
|
+
return url;
|
|
893
|
+
}
|
|
894
|
+
const protocolRelative = Symbol.for("ufo:protocolRelative");
|
|
895
|
+
function parseURL(input = "", defaultProto) {
|
|
896
|
+
const _specialProtoMatch = input.match(/^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i);
|
|
897
|
+
if (_specialProtoMatch) {
|
|
898
|
+
const [, _proto, _pathname = ""] = _specialProtoMatch;
|
|
899
|
+
return {
|
|
900
|
+
protocol: _proto.toLowerCase(),
|
|
901
|
+
pathname: _pathname,
|
|
902
|
+
href: _proto + _pathname,
|
|
903
|
+
auth: "",
|
|
904
|
+
host: "",
|
|
905
|
+
search: "",
|
|
906
|
+
hash: ""
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
if (!hasProtocol(input, { acceptRelative: true })) return defaultProto ? parseURL(defaultProto + input) : parsePath(input);
|
|
910
|
+
const [, protocol = "", auth, hostAndPath = ""] = input.replace(/\\/g, "/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/) || [];
|
|
911
|
+
let [, host = "", path = ""] = hostAndPath.match(/([^#/?]*)(.*)?/) || [];
|
|
912
|
+
if (protocol === "file:") path = path.replace(/\/(?=[A-Za-z]:)/, "");
|
|
913
|
+
const { pathname, search, hash } = parsePath(path);
|
|
914
|
+
return {
|
|
915
|
+
protocol: protocol.toLowerCase(),
|
|
916
|
+
auth: auth ? auth.slice(0, Math.max(0, auth.length - 1)) : "",
|
|
917
|
+
host,
|
|
918
|
+
pathname,
|
|
919
|
+
search,
|
|
920
|
+
hash,
|
|
921
|
+
[protocolRelative]: !protocol
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
function parsePath(input = "") {
|
|
925
|
+
const [pathname = "", search = "", hash = ""] = (input.match(/([^#?]*)(\?[^#]*)?(#.*)?/) || []).splice(1);
|
|
926
|
+
return {
|
|
927
|
+
pathname,
|
|
928
|
+
search,
|
|
929
|
+
hash
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
function stringifyParsedURL(parsed) {
|
|
933
|
+
const pathname = parsed.pathname || "";
|
|
934
|
+
const search = parsed.search ? (parsed.search.startsWith("?") ? "" : "?") + parsed.search : "";
|
|
935
|
+
const hash = parsed.hash || "";
|
|
936
|
+
const auth = parsed.auth ? parsed.auth + "@" : "";
|
|
937
|
+
const host = parsed.host || "";
|
|
938
|
+
return (parsed.protocol || parsed[protocolRelative] ? (parsed.protocol || "") + "//" : "") + auth + host + pathname + search + hash;
|
|
939
|
+
}
|
|
940
|
+
//#endregion
|
|
880
941
|
//#region src/user-api/credential.ts
|
|
881
942
|
function userApiApplication(input) {
|
|
882
943
|
if (!input || typeof input.applicationId !== "string" || !/^[A-Za-z0-9_-]{1,128}$(?![\s\S])/.test(input.applicationId) || input.forceRefresh !== void 0 && typeof input.forceRefresh !== "boolean") throw new TypeError("User API credential input is invalid");
|
|
@@ -3230,6 +3291,39 @@ function createServerAuth(options) {
|
|
|
3230
3291
|
getReceivedInvitation(invitationId) {
|
|
3231
3292
|
return organizationRead(`received-invitations/${normalizeIdInput(invitationId)}`, void 0, normalizeReceivedInvitation);
|
|
3232
3293
|
},
|
|
3294
|
+
async startGoogleAccountRecovery(input) {
|
|
3295
|
+
if (authorization) throw new AuthError("state_conflict", 409);
|
|
3296
|
+
const body = googleRecoveryInput(input, false);
|
|
3297
|
+
return normalizeGoogleRecovery(await requestJson(joinURL(authOrigin, "api/v1/auth/google-account-recovery/start"), {
|
|
3298
|
+
fetch: fetchImpl,
|
|
3299
|
+
timeoutMs,
|
|
3300
|
+
method: "POST",
|
|
3301
|
+
credentials: "include",
|
|
3302
|
+
headers: {
|
|
3303
|
+
...authHeaders(),
|
|
3304
|
+
"content-type": "application/json; charset=utf-8"
|
|
3305
|
+
},
|
|
3306
|
+
body,
|
|
3307
|
+
mapError: fromGoogleRecoveryError
|
|
3308
|
+
}), now());
|
|
3309
|
+
},
|
|
3310
|
+
async completeGoogleAccountRecovery(input) {
|
|
3311
|
+
if (authorization) throw new AuthError("state_conflict", 409);
|
|
3312
|
+
if (!cookie) throw new AuthError("authentication_required", 401);
|
|
3313
|
+
const body = googleRecoveryInput(input, true);
|
|
3314
|
+
return normalizeGoogleRecoveryCompletion(await requestJson(joinURL(authOrigin, "api/v1/auth/google-account-recovery/complete"), {
|
|
3315
|
+
fetch: fetchImpl,
|
|
3316
|
+
timeoutMs,
|
|
3317
|
+
method: "POST",
|
|
3318
|
+
credentials: "include",
|
|
3319
|
+
headers: {
|
|
3320
|
+
...authHeaders(),
|
|
3321
|
+
"content-type": "application/json; charset=utf-8"
|
|
3322
|
+
},
|
|
3323
|
+
body,
|
|
3324
|
+
mapError: fromGoogleRecoveryError
|
|
3325
|
+
}));
|
|
3326
|
+
},
|
|
3233
3327
|
async signInWithSocialIdToken(input) {
|
|
3234
3328
|
if (authorization) throw new AuthError("state_conflict", 409);
|
|
3235
3329
|
const body = socialIdTokenRequest(normalizeSocialIdTokenInput(input));
|
|
@@ -10,8 +10,8 @@ interface UserApiCredential {
|
|
|
10
10
|
}
|
|
11
11
|
//#endregion
|
|
12
12
|
//#region src/errors.d.ts
|
|
13
|
-
type AuthErrorCode = "invalid_credentials" | "invalid_auth_input" | "account_conflict" | "password_reset_invalid" | "authentication_required" | "request_origin_denied" | "invalid_request" | "invalid_invitation" | "invitation_unavailable" | "recipient_unavailable" | "invitation_recipient_mismatch" | "invitation_recovery_required" | "membership_removal_recovery_required" | "email_verification_required" | "invalid_workspace_selection" | "organization_context_too_large" | "credential_rate_limited" | "auth_request_rate_limited" | "state_conflict" | "access_denied" | "platform_target_unavailable" | "platform_quorum_unavailable" | "platform_recovery_required" | "identity_authority_unavailable" | "two_factor_required" | "two_factor_code_invalid" | "two_factor_challenge_expired" | "two_factor_locked" | "recent_sign_in_required" | "enterprise_recovery_required" | "recent_authentication_required" | "organization_closure_confirmation_mismatch" | "organization_closure_cancellation_ended" | "ceremony_return_refused" | "password_sign_in_required";
|
|
14
|
-
type AuthErrorStatus = 400 | 401 | 403 | 404 | 405 | 409 | 413 | 415 | 422 | 429 | 503;
|
|
13
|
+
type AuthErrorCode = "invalid_credentials" | "invalid_auth_input" | "account_conflict" | "social_signup_required" | "google_recovery_in_progress" | "google_recovery_not_required" | "google_recovery_invalid" | "google_recovery_expired" | "google_recovery_account_mismatch" | "password_reset_invalid" | "authentication_required" | "request_origin_denied" | "invalid_request" | "invalid_invitation" | "invitation_unavailable" | "recipient_unavailable" | "invitation_recipient_mismatch" | "invitation_recovery_required" | "membership_removal_recovery_required" | "email_verification_required" | "invalid_workspace_selection" | "organization_context_too_large" | "credential_rate_limited" | "auth_request_rate_limited" | "organization_slug_unavailable" | "state_conflict" | "access_denied" | "platform_target_unavailable" | "platform_quorum_unavailable" | "platform_recovery_required" | "identity_authority_unavailable" | "two_factor_required" | "two_factor_code_invalid" | "two_factor_challenge_expired" | "two_factor_locked" | "recent_sign_in_required" | "enterprise_recovery_required" | "recent_authentication_required" | "organization_closure_confirmation_mismatch" | "organization_closure_cancellation_ended" | "ceremony_return_refused" | "password_sign_in_required";
|
|
14
|
+
type AuthErrorStatus = 400 | 401 | 403 | 404 | 405 | 409 | 410 | 413 | 415 | 422 | 429 | 503;
|
|
15
15
|
declare class AuthError extends Error {
|
|
16
16
|
readonly code: AuthErrorCode;
|
|
17
17
|
readonly status: AuthErrorStatus;
|
|
@@ -346,6 +346,41 @@ interface EnterpriseConnection {
|
|
|
346
346
|
roleMappingConfigured: boolean;
|
|
347
347
|
updatedAt: Date;
|
|
348
348
|
}
|
|
349
|
+
/** OIDC self-service configuration. Client secrets are write-only. */
|
|
350
|
+
interface EnterpriseConnectionSetup {
|
|
351
|
+
id: string;
|
|
352
|
+
revision: number;
|
|
353
|
+
issuer: string;
|
|
354
|
+
clientId: string;
|
|
355
|
+
enabled: boolean;
|
|
356
|
+
memberJit: boolean;
|
|
357
|
+
domain: string;
|
|
358
|
+
domainVerified: boolean;
|
|
359
|
+
validatedAt: Date | null;
|
|
360
|
+
testedAt: Date | null;
|
|
361
|
+
dnsRecordName: string;
|
|
362
|
+
dnsRecordValue: string;
|
|
363
|
+
challengeExpiresAt: Date;
|
|
364
|
+
redirectUri: string;
|
|
365
|
+
}
|
|
366
|
+
interface CreateEnterpriseConnectionInput {
|
|
367
|
+
/** Keep this UUID unchanged when retrying the same creation attempt. */
|
|
368
|
+
requestId: string;
|
|
369
|
+
issuer: string;
|
|
370
|
+
clientId: string;
|
|
371
|
+
clientSecret: string;
|
|
372
|
+
domain: string;
|
|
373
|
+
memberJit: boolean;
|
|
374
|
+
}
|
|
375
|
+
interface UpdateEnterpriseConnectionInput {
|
|
376
|
+
expectedRevision: number;
|
|
377
|
+
issuer: string;
|
|
378
|
+
clientId: string;
|
|
379
|
+
/** Omit to keep the current secret. It cannot be read back. */
|
|
380
|
+
clientSecret?: string;
|
|
381
|
+
memberJit: boolean;
|
|
382
|
+
}
|
|
383
|
+
type EnterpriseConnectionAction = "challenge" | "verify" | "validate" | "enable" | "disable" | "archive";
|
|
349
384
|
interface ScimCredentialState {
|
|
350
385
|
status: "active" | "revoked" | "unissued";
|
|
351
386
|
revision: number | null;
|
|
@@ -545,6 +580,23 @@ interface FinuevaAuthClient {
|
|
|
545
580
|
signIn(input: SignInInput): Promise<AuthSession>;
|
|
546
581
|
/** Cookie-only. A manual owner or admin reads the organization's enterprise connection status. */
|
|
547
582
|
listEnterpriseConnections(organizationId: string): Promise<EnterpriseConnection[]>;
|
|
583
|
+
listEnterpriseConnectionSetups(organizationId: string): Promise<EnterpriseConnectionSetup[]>;
|
|
584
|
+
/** Test OIDC without changing the admin's session or creating membership. Navigate to the returned HTTPS URL. */
|
|
585
|
+
startEnterpriseConnectionTest(organizationId: string, connectionId: string, input: {
|
|
586
|
+
expectedRevision: number;
|
|
587
|
+
applicationId: string;
|
|
588
|
+
returnTo: string;
|
|
589
|
+
}): Promise<{
|
|
590
|
+
url: string;
|
|
591
|
+
}>;
|
|
592
|
+
createEnterpriseConnection(organizationId: string, input: CreateEnterpriseConnectionInput): Promise<EnterpriseConnectionSetup>;
|
|
593
|
+
updateEnterpriseConnection(organizationId: string, connectionId: string, input: UpdateEnterpriseConnectionInput): Promise<EnterpriseConnectionSetup>;
|
|
594
|
+
actOnEnterpriseConnection(organizationId: string, connectionId: string, input: {
|
|
595
|
+
expectedRevision: number;
|
|
596
|
+
action: EnterpriseConnectionAction;
|
|
597
|
+
}): Promise<EnterpriseConnectionSetup | {
|
|
598
|
+
removed: true;
|
|
599
|
+
}>;
|
|
548
600
|
/** Cookie-only. Reads SCIM credential state for an eligible managed-lifecycle connection. */
|
|
549
601
|
getScimCredential(organizationId: string, connectionId: string): Promise<ScimCredentialState>;
|
|
550
602
|
issueScimCredential(organizationId: string, connectionId: string): Promise<ScimCredentialIssuance>;
|
|
@@ -588,4 +640,4 @@ interface FinuevaAuthClient {
|
|
|
588
640
|
onSessionChange(listener: (session: AuthSession | null) => void): () => void;
|
|
589
641
|
}
|
|
590
642
|
//#endregion
|
|
591
|
-
export {
|
|
643
|
+
export { PasskeyInventory as $, EnterpriseConnection as A, UpdateOrganizationDisplayInput as At, OrganizationDisplay as B, CreatedOrganizationTeam as C, SuspendedOrganizationMember as Ct, DepartedOrganizationMemberPage as D, TwoFactorStatus as Dt, DepartedOrganizationMember as E, TwoFactorEnrollment as Et, InvitationDecline as F, AuthErrorCode as Ft, OrganizationMemberPage as G, OrganizationInvitationPage as H, OrganizationClosure as I, AuthErrorStatus as It, OrganizationTeam as J, OrganizationPage as K, OrganizationClosureCancelInput as L, UserApiCredential as Lt, EnterpriseConnectionSetup as M, UpdateProfileInput as Mt, FinuevaAuthClient as N, WorkspaceSelection as Nt, DriveCredential as O, TwoFactorStepUpInput as Ot, InvitationAcceptance as P, AuthError as Pt, OrganizationWorkspaceSelection as Q, OrganizationClosureStartInput as R, UserApiCredentialInput as Rt, CreatedOrganizationMemberInvitation as S, SocialIdTokenProvider as St, DeletedOrganizationTeam as T, SuspendedOrganizationMemberStatus as Tt, OrganizationMember as U, OrganizationInvitation as V, OrganizationMemberAuthority as W, OrganizationTeamMemberPage as X, OrganizationTeamDisplay as Y, OrganizationTeamPage as Z, ClosingOrganization as _, ScimCredentialIssuance as _t, AuthPersistence as a, PlatformRoleApproval as at, CreateOrganizationMemberInvitationInput as b, SignInInput as bt, AuthSessionInventory as c, PlatformStatus as ct, AuthUser as d, RecentAuthenticationStatus as dt, PasskeySummary as et, CanceledOrganizationInvitation as f, RemovedOrganizationMember as ft, CeremonyReturnInput as g, RotateScimCredentialInput as gt, CeremonyRecentAuthenticationRequest as h, RestoredOrganizationMember as ht, AuthOrganization as i, PlatformRoleApplied as it, EnterpriseConnectionAction as j, UpdateOrganizationTeamDisplayInput as jt, DriveCredentialInput as k, UpdateEnterpriseConnectionInput as kt, AuthSessionSummary as l, ReceivedOrganizationInvitation as lt, CeremonyHandoffInput as m, ResentOrganizationInvitation as mt, AddedOrganizationTeamMember as n, PlatformBootstrapRoleChangeInput as nt, AuthPersistenceDriver as o, PlatformRoleChangeRecentAuthenticationInput as ot, CeremonyHandoff as p, RemovedOrganizationTeamMember as pt, OrganizationPageInput as q, AuthClientOptions as r, PlatformRole as rt, AuthSession as s, PlatformRoleFirstApproval as st, AcceptInvitationInput as t, PersonalWorkspaceSelection as tt, AuthState as u, ReceivedOrganizationInvitationPage as ut, ClosingOrganizationList as v, ScimCredentialState as vt, DeclineInvitationInput as w, SuspendedOrganizationMemberPage as wt, CreatedOrganization as x, SocialIdTokenInput as xt, CreateEnterpriseConnectionInput as y, SendVerificationEmailInput as yt, OrganizationDeparture as z };
|