@finueva/auth 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/device.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as OrganizationPage, D as OrganizationTeamMemberPage, E as OrganizationTeamDisplay, G as SocialIdTokenProvider, J as UpdateProfileInput, K as UpdateOrganizationDisplayInput, O as OrganizationTeamPage, Q as AuthErrorStatus, R as ReceivedOrganizationInvitation, S as OrganizationMemberPage, T as OrganizationTeam, W as SocialIdTokenInput, X as AuthError, Z as AuthErrorCode, _ as OrganizationDisplay, b as OrganizationMember, d as CreatedOrganizationMemberInvitation, f as CreatedOrganizationTeam, m as DriveCredentialInput, o as AuthSession, p as DriveCredential, q as UpdateOrganizationTeamDisplayInput, r as AuthOrganization, u as CreateOrganizationMemberInvitationInput, v as OrganizationInvitation, w as OrganizationPageInput, x as OrganizationMemberAuthority, y as OrganizationInvitationPage, z as ReceivedOrganizationInvitationPage } from "./types-Dpy17xNC.js";
1
+ import { $ as UserApiCredential, C as OrganizationPage, D as OrganizationTeamMemberPage, E as OrganizationTeamDisplay, G as SocialIdTokenProvider, J as UpdateProfileInput, K as UpdateOrganizationDisplayInput, O as OrganizationTeamPage, Q as AuthErrorStatus, R as ReceivedOrganizationInvitation, S as OrganizationMemberPage, T as OrganizationTeam, W as SocialIdTokenInput, X as AuthError, Z as AuthErrorCode, _ as OrganizationDisplay, b as OrganizationMember, d as CreatedOrganizationMemberInvitation, et as UserApiCredentialInput, f as CreatedOrganizationTeam, m as DriveCredentialInput, o as AuthSession, p as DriveCredential, q as UpdateOrganizationTeamDisplayInput, r as AuthOrganization, u as CreateOrganizationMemberInvitationInput, v as OrganizationInvitation, w as OrganizationPageInput, x as OrganizationMemberAuthority, y as OrganizationInvitationPage, z as ReceivedOrganizationInvitationPage } from "./types-CqFT4G95.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 {
@@ -64,9 +64,10 @@ interface DeviceAuthClient {
64
64
  updateProfile(input: UpdateProfileInput): Promise<AuthSession>;
65
65
  changePassword(currentPassword: string, newPassword: string, revokeOtherSessions?: boolean): Promise<AuthSession>;
66
66
  getDriveCredential(input: DriveCredentialInput): Promise<DriveCredential>;
67
+ getUserApiCredential(input: UserApiCredentialInput): Promise<UserApiCredential>;
67
68
  revokeCurrentDevice(): Promise<void>;
68
69
  revokeAllSessions(): Promise<void>;
69
70
  }
70
71
  declare function createDeviceAuth(options: DeviceAuthOptions): DeviceAuthClient;
71
72
  //#endregion
72
- export { AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type CreateOrganizationMemberInvitationInput, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, DeviceAuthClient, DeviceAuthOptions, DeviceAuthorization, DeviceAuthorizationError, DeviceAuthorizationErrorCode, DeviceToken, DeviceTokenPersistence, type OrganizationDisplay, type OrganizationInvitation, type OrganizationInvitationPage, type OrganizationMember, type OrganizationMemberAuthority, type OrganizationMemberPage, type OrganizationPage, type OrganizationPageInput, type OrganizationTeam, type OrganizationTeamDisplay, type OrganizationTeamMemberPage, type OrganizationTeamPage, PollDeviceOptions, type ReceivedOrganizationInvitation, type ReceivedOrganizationInvitationPage, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, createDeviceAuth };
73
+ export { AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type CreateOrganizationMemberInvitationInput, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, DeviceAuthClient, DeviceAuthOptions, DeviceAuthorization, DeviceAuthorizationError, DeviceAuthorizationErrorCode, DeviceToken, DeviceTokenPersistence, type OrganizationDisplay, type OrganizationInvitation, type OrganizationInvitationPage, type OrganizationMember, type OrganizationMemberAuthority, type OrganizationMemberPage, type OrganizationPage, type OrganizationPageInput, type OrganizationTeam, type OrganizationTeamDisplay, type OrganizationTeamMemberPage, type OrganizationTeamPage, PollDeviceOptions, type ReceivedOrganizationInvitation, type ReceivedOrganizationInvitationPage, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UserApiCredential, type UserApiCredentialInput, createDeviceAuth };
package/dist/device.js CHANGED
@@ -173,6 +173,109 @@ function stringifyParsedURL(parsed) {
173
173
  return (parsed.protocol || parsed[protocolRelative] ? (parsed.protocol || "") + "//" : "") + auth + host + pathname + search + hash;
174
174
  }
175
175
  //#endregion
176
+ //#region src/errors.ts
177
+ const messages = {
178
+ invalid_credentials: "The credentials are invalid.",
179
+ invalid_auth_input: "The authentication input is invalid.",
180
+ account_conflict: "The account is not available.",
181
+ password_reset_invalid: "The password reset request is invalid.",
182
+ authentication_required: "Authentication is required.",
183
+ request_origin_denied: "The request origin is not allowed.",
184
+ invalid_request: "The request is invalid.",
185
+ invalid_invitation: "The invitation is invalid.",
186
+ invitation_unavailable: "The invitation is not available.",
187
+ recipient_unavailable: "The recipient is unavailable.",
188
+ invitation_recipient_mismatch: "The invitation cannot be accepted by this account.",
189
+ invitation_recovery_required: "Invitation administration requires separate recovery.",
190
+ email_verification_required: "Email verification is required.",
191
+ invalid_workspace_selection: "The workspace selection is invalid.",
192
+ organization_context_too_large: "The organization context is too large.",
193
+ credential_rate_limited: "Credential requests are temporarily limited.",
194
+ auth_request_rate_limited: "Authentication requests are temporarily limited.",
195
+ state_conflict: "The authentication state conflicts with the request.",
196
+ access_denied: "Access is denied.",
197
+ platform_target_unavailable: "The platform administration target is unavailable.",
198
+ platform_quorum_unavailable: "Platform administration quorum is unavailable.",
199
+ platform_recovery_required: "Platform administration requires separate recovery.",
200
+ identity_authority_unavailable: "Authentication is temporarily unavailable."
201
+ };
202
+ var AuthError = class extends Error {
203
+ code;
204
+ status;
205
+ retryAfterSeconds;
206
+ constructor(code, status, retryAfterSeconds) {
207
+ super(messages[code]);
208
+ this.name = "AuthError";
209
+ this.code = code;
210
+ this.status = status;
211
+ this.retryAfterSeconds = retryAfterSeconds;
212
+ }
213
+ };
214
+ //#endregion
215
+ //#region src/user-api/credential.ts
216
+ function userApiApplication(input) {
217
+ 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");
218
+ return input.applicationId;
219
+ }
220
+ function normalizeUserApiCredential(value, startedAt) {
221
+ if (!value || typeof value !== "object" || Array.isArray(value) || !("tokenType" in value) || value.tokenType !== "Bearer" || !("token" in value) || typeof value.token !== "string" || value.token.length + 7 > 16 * 1024 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value.token) || !("expiresIn" in value) || typeof value.expiresIn !== "number" || !Number.isInteger(value.expiresIn) || value.expiresIn < 1 || value.expiresIn > 840 || Object.keys(value).sort().join(",") !== "expiresIn,token,tokenType") throw new AuthError("identity_authority_unavailable", 503);
222
+ return {
223
+ tokenType: "Bearer",
224
+ token: value.token,
225
+ expiresAt: new Date(startedAt + value.expiresIn * 1e3)
226
+ };
227
+ }
228
+ function createUserApiCredentialCache(issue, now) {
229
+ let generation = 0;
230
+ let cached;
231
+ let pending;
232
+ const copy = (value) => ({
233
+ ...value,
234
+ expiresAt: new Date(value.expiresAt)
235
+ });
236
+ return {
237
+ hasAuthority: () => Boolean(cached || pending),
238
+ clear() {
239
+ generation += 1;
240
+ cached = void 0;
241
+ pending = void 0;
242
+ },
243
+ async get(input) {
244
+ const applicationId = userApiApplication(input);
245
+ if (pending) {
246
+ if (pending.applicationId !== applicationId) throw new AuthError("state_conflict", 409);
247
+ return copy(await pending.request);
248
+ }
249
+ const startedAt = now();
250
+ if (!input.forceRefresh && cached?.applicationId === applicationId && cached.expiresAt - startedAt > 12e4) return {
251
+ tokenType: "Bearer",
252
+ token: cached.token,
253
+ expiresAt: new Date(cached.expiresAt)
254
+ };
255
+ cached = void 0;
256
+ const epoch = generation;
257
+ const request = (async () => {
258
+ const value = normalizeUserApiCredential(await issue(applicationId), startedAt);
259
+ if (epoch !== generation) throw new AuthError("state_conflict", 409);
260
+ if (now() < startedAt || value.expiresAt.getTime() <= now()) throw new AuthError("authentication_required", 401);
261
+ cached = {
262
+ applicationId,
263
+ token: value.token,
264
+ expiresAt: value.expiresAt.getTime()
265
+ };
266
+ return value;
267
+ })().finally(() => {
268
+ if (pending?.request === request) pending = void 0;
269
+ });
270
+ pending = {
271
+ applicationId,
272
+ request
273
+ };
274
+ return copy(await request);
275
+ }
276
+ };
277
+ }
278
+ //#endregion
176
279
  //#region ../../node_modules/.pnpm/destr@2.0.5/node_modules/destr/dist/index.mjs
177
280
  const suspectProtoRx = /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/;
178
281
  const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
@@ -436,45 +539,6 @@ function createFetch(globalOptions = {}) {
436
539
  return $fetch;
437
540
  }
438
541
  //#endregion
439
- //#region src/errors.ts
440
- const messages = {
441
- invalid_credentials: "The credentials are invalid.",
442
- invalid_auth_input: "The authentication input is invalid.",
443
- account_conflict: "The account is not available.",
444
- password_reset_invalid: "The password reset request is invalid.",
445
- authentication_required: "Authentication is required.",
446
- request_origin_denied: "The request origin is not allowed.",
447
- invalid_request: "The request is invalid.",
448
- invalid_invitation: "The invitation is invalid.",
449
- invitation_unavailable: "The invitation is not available.",
450
- recipient_unavailable: "The recipient is unavailable.",
451
- invitation_recipient_mismatch: "The invitation cannot be accepted by this account.",
452
- invitation_recovery_required: "Invitation administration requires separate recovery.",
453
- email_verification_required: "Email verification is required.",
454
- invalid_workspace_selection: "The workspace selection is invalid.",
455
- organization_context_too_large: "The organization context is too large.",
456
- credential_rate_limited: "Credential requests are temporarily limited.",
457
- auth_request_rate_limited: "Authentication requests are temporarily limited.",
458
- state_conflict: "The authentication state conflicts with the request.",
459
- access_denied: "Access is denied.",
460
- platform_target_unavailable: "The platform administration target is unavailable.",
461
- platform_quorum_unavailable: "Platform administration quorum is unavailable.",
462
- platform_recovery_required: "Platform administration requires separate recovery.",
463
- identity_authority_unavailable: "Authentication is temporarily unavailable."
464
- };
465
- var AuthError = class extends Error {
466
- code;
467
- status;
468
- retryAfterSeconds;
469
- constructor(code, status, retryAfterSeconds) {
470
- super(messages[code]);
471
- this.name = "AuthError";
472
- this.code = code;
473
- this.status = status;
474
- this.retryAfterSeconds = retryAfterSeconds;
475
- }
476
- };
477
- //#endregion
478
542
  //#region src/shared.ts
479
543
  const DRIVE_CREDENTIAL_LIFETIME_SECONDS = 840;
480
544
  const id = /^[A-Za-z0-9_-]{1,128}$/;
@@ -1165,7 +1229,18 @@ function createDeviceAuth(options) {
1165
1229
  let authorityTail = Promise.resolve();
1166
1230
  let persistenceTail = Promise.resolve();
1167
1231
  let persistencePending = 0;
1232
+ const userApiCredentials = createUserApiCredentialCache(async (applicationId) => {
1233
+ const authority = await serializeAuthority(async () => ({
1234
+ current: await readToken(),
1235
+ generation: authorityGeneration
1236
+ }));
1237
+ if (!authority.current) throw new AuthError("authentication_required", 401);
1238
+ const response = await authenticated("user-api-credential", authority.current, { applicationId });
1239
+ if (authority.generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
1240
+ return response.value;
1241
+ }, now);
1168
1242
  function clearCredential() {
1243
+ userApiCredentials.clear();
1169
1244
  credential = void 0;
1170
1245
  selectedWorkspaceKey = void 0;
1171
1246
  credentialGeneration += 1;
@@ -1782,6 +1857,9 @@ function createDeviceAuth(options) {
1782
1857
  return session;
1783
1858
  }, true);
1784
1859
  },
1860
+ getUserApiCredential(input) {
1861
+ return userApiCredentials.get(input);
1862
+ },
1785
1863
  getDriveCredential(input) {
1786
1864
  let workspace;
1787
1865
  let forceRefresh;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as PersonalWorkspaceSelection, B as RecentAuthenticationStatus, C as OrganizationPage, D as OrganizationTeamMemberPage, E as OrganizationTeamDisplay, F as PlatformRoleChangeRecentAuthenticationInput, G as SocialIdTokenProvider, H as SendVerificationEmailInput, I as PlatformRoleFirstApproval, J as UpdateProfileInput, K as UpdateOrganizationDisplayInput, L as PlatformStatus, M as PlatformRole, N as PlatformRoleApplied, O as OrganizationTeamPage, P as PlatformRoleApproval, Q as AuthErrorStatus, R as ReceivedOrganizationInvitation, S as OrganizationMemberPage, T as OrganizationTeam, U as SignInInput, V as ResentOrganizationInvitation, W as SocialIdTokenInput, X as AuthError, Y as WorkspaceSelection, Z as AuthErrorCode, _ as OrganizationDisplay, a as AuthPersistenceDriver, b as OrganizationMember, c as AuthUser, d as CreatedOrganizationMemberInvitation, f as CreatedOrganizationTeam, g as InvitationAcceptance, h as FinuevaAuthClient, i as AuthPersistence, j as PlatformBootstrapRoleChangeInput, k as OrganizationWorkspaceSelection, l as CanceledOrganizationInvitation, m as DriveCredentialInput, n as AuthClientOptions, o as AuthSession, p as DriveCredential, q as UpdateOrganizationTeamDisplayInput, r as AuthOrganization, s as AuthState, t as AcceptInvitationInput, u as CreateOrganizationMemberInvitationInput, v as OrganizationInvitation, w as OrganizationPageInput, x as OrganizationMemberAuthority, y as OrganizationInvitationPage, z as ReceivedOrganizationInvitationPage } from "./types-Dpy17xNC.js";
1
+ import { $ as UserApiCredential, A as PersonalWorkspaceSelection, B as RecentAuthenticationStatus, C as OrganizationPage, D as OrganizationTeamMemberPage, E as OrganizationTeamDisplay, F as PlatformRoleChangeRecentAuthenticationInput, G as SocialIdTokenProvider, H as SendVerificationEmailInput, I as PlatformRoleFirstApproval, J as UpdateProfileInput, K as UpdateOrganizationDisplayInput, L as PlatformStatus, M as PlatformRole, N as PlatformRoleApplied, O as OrganizationTeamPage, P as PlatformRoleApproval, Q as AuthErrorStatus, R as ReceivedOrganizationInvitation, S as OrganizationMemberPage, T as OrganizationTeam, U as SignInInput, V as ResentOrganizationInvitation, W as SocialIdTokenInput, X as AuthError, Y as WorkspaceSelection, Z as AuthErrorCode, _ as OrganizationDisplay, a as AuthPersistenceDriver, b as OrganizationMember, c as AuthUser, d as CreatedOrganizationMemberInvitation, et as UserApiCredentialInput, f as CreatedOrganizationTeam, g as InvitationAcceptance, h as FinuevaAuthClient, i as AuthPersistence, j as PlatformBootstrapRoleChangeInput, k as OrganizationWorkspaceSelection, l as CanceledOrganizationInvitation, m as DriveCredentialInput, n as AuthClientOptions, o as AuthSession, p as DriveCredential, q as UpdateOrganizationTeamDisplayInput, r as AuthOrganization, s as AuthState, t as AcceptInvitationInput, u as CreateOrganizationMemberInvitationInput, v as OrganizationInvitation, w as OrganizationPageInput, x as OrganizationMemberAuthority, y as OrganizationInvitationPage, z as ReceivedOrganizationInvitationPage } from "./types-CqFT4G95.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 CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DriveCredential, type DriveCredentialInput, type FinuevaAuthClient, type InvitationAcceptance, 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 ResentOrganizationInvitation, type SendVerificationEmailInput, type SignInInput, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UpdateProfileInput, type WorkspaceSelection, createAuthClient };
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 CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DriveCredential, type DriveCredentialInput, type FinuevaAuthClient, type InvitationAcceptance, 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 ResentOrganizationInvitation, type SendVerificationEmailInput, type SignInInput, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UpdateProfileInput, type UserApiCredential, type UserApiCredentialInput, type WorkspaceSelection, createAuthClient };
package/dist/index.js CHANGED
@@ -4456,6 +4456,70 @@ function byteLength(value) {
4456
4456
  return new TextEncoder().encode(value).byteLength;
4457
4457
  }
4458
4458
  //#endregion
4459
+ //#region src/user-api/credential.ts
4460
+ function userApiApplication(input) {
4461
+ 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");
4462
+ return input.applicationId;
4463
+ }
4464
+ function normalizeUserApiCredential(value, startedAt) {
4465
+ if (!value || typeof value !== "object" || Array.isArray(value) || !("tokenType" in value) || value.tokenType !== "Bearer" || !("token" in value) || typeof value.token !== "string" || value.token.length + 7 > 16 * 1024 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value.token) || !("expiresIn" in value) || typeof value.expiresIn !== "number" || !Number.isInteger(value.expiresIn) || value.expiresIn < 1 || value.expiresIn > 840 || Object.keys(value).sort().join(",") !== "expiresIn,token,tokenType") throw new AuthError("identity_authority_unavailable", 503);
4466
+ return {
4467
+ tokenType: "Bearer",
4468
+ token: value.token,
4469
+ expiresAt: new Date(startedAt + value.expiresIn * 1e3)
4470
+ };
4471
+ }
4472
+ function createUserApiCredentialCache(issue, now) {
4473
+ let generation = 0;
4474
+ let cached;
4475
+ let pending;
4476
+ const copy = (value) => ({
4477
+ ...value,
4478
+ expiresAt: new Date(value.expiresAt)
4479
+ });
4480
+ return {
4481
+ hasAuthority: () => Boolean(cached || pending),
4482
+ clear() {
4483
+ generation += 1;
4484
+ cached = void 0;
4485
+ pending = void 0;
4486
+ },
4487
+ async get(input) {
4488
+ const applicationId = userApiApplication(input);
4489
+ if (pending) {
4490
+ if (pending.applicationId !== applicationId) throw new AuthError("state_conflict", 409);
4491
+ return copy(await pending.request);
4492
+ }
4493
+ const startedAt = now();
4494
+ if (!input.forceRefresh && cached?.applicationId === applicationId && cached.expiresAt - startedAt > 12e4) return {
4495
+ tokenType: "Bearer",
4496
+ token: cached.token,
4497
+ expiresAt: new Date(cached.expiresAt)
4498
+ };
4499
+ cached = void 0;
4500
+ const epoch = generation;
4501
+ const request = (async () => {
4502
+ const value = normalizeUserApiCredential(await issue(applicationId), startedAt);
4503
+ if (epoch !== generation) throw new AuthError("state_conflict", 409);
4504
+ if (now() < startedAt || value.expiresAt.getTime() <= now()) throw new AuthError("authentication_required", 401);
4505
+ cached = {
4506
+ applicationId,
4507
+ token: value.token,
4508
+ expiresAt: value.expiresAt.getTime()
4509
+ };
4510
+ return value;
4511
+ })().finally(() => {
4512
+ if (pending?.request === request) pending = void 0;
4513
+ });
4514
+ pending = {
4515
+ applicationId,
4516
+ request
4517
+ };
4518
+ return copy(await request);
4519
+ }
4520
+ };
4521
+ }
4522
+ //#endregion
4459
4523
  //#region src/client.ts
4460
4524
  const REFRESH_WINDOW_MS = 120 * 1e3;
4461
4525
  const RECENT_AUTHENTICATION_BROWSER_HEADER = "x-finueva-recent-auth-browser";
@@ -4468,11 +4532,18 @@ function createAuthClient(options) {
4468
4532
  if (typeof fetchImpl !== "function") throw new TypeError("fetch is required");
4469
4533
  const now = options.now ?? Date.now;
4470
4534
  const timeoutMs = normalizeTimeout(options.timeoutMs);
4535
+ const userApiCredentials = createUserApiCredentialCache((applicationId) => requestJson(joinURL(authOrigin, "api/v1/auth/user-api-credential"), {
4536
+ fetch: fetchImpl,
4537
+ timeoutMs,
4538
+ method: "POST",
4539
+ headers: { "content-type": "application/json; charset=utf-8" },
4540
+ body: { applicationId }
4541
+ }), now);
4471
4542
  const betterAuth = createAuthClient$1({
4472
4543
  baseURL: authOrigin,
4473
4544
  basePath: "/api/v1/auth",
4474
4545
  fetchOptions: {
4475
- customFetchImpl: fetchImpl,
4546
+ customFetchImpl: fetchBetterAuth,
4476
4547
  credentials: "include",
4477
4548
  retry: 0,
4478
4549
  timeout: timeoutMs
@@ -4508,6 +4579,15 @@ function createAuthClient(options) {
4508
4579
  let signalRefreshPending = false;
4509
4580
  let signalRefreshScheduled = false;
4510
4581
  let signalRefreshRequest;
4582
+ let betterAuthTransportSequence = 0;
4583
+ async function fetchBetterAuth(input, init) {
4584
+ const request = new Request(input, init);
4585
+ const url = new URL(request.url);
4586
+ if (!authStateStarted || request.method !== "GET" || url.origin !== authOrigin || url.pathname !== "/api/v1/auth/get-session" || signOutRequest || activeAccountMutationGeneration !== void 0) return fetchImpl(input, init);
4587
+ betterAuthTransportSequence += 1;
4588
+ const response = await readAuthoritySession(authorityGeneration, request);
4589
+ return new Response(JSON.stringify(response.value), { headers: { "content-type": "application/json" } });
4590
+ }
4511
4591
  function advanceAuthorityGeneration() {
4512
4592
  recentAuthenticationStartAttempt = void 0;
4513
4593
  return ++authorityGeneration;
@@ -4569,12 +4649,13 @@ function createAuthClient(options) {
4569
4649
  authoritative: false
4570
4650
  });
4571
4651
  });
4572
- getSession().catch(() => void 0);
4652
+ if (typeof window === "undefined") getSession().catch(() => void 0);
4573
4653
  }
4574
4654
  function subscribeToSessionSignals() {
4575
4655
  if (sessionSignalSubscribed) return;
4576
4656
  sessionSignalSubscribed = true;
4577
4657
  let initialized = false;
4658
+ let transportSequence = betterAuthTransportSequence;
4578
4659
  betterAuth.useSession.subscribe((state) => {
4579
4660
  const refetching = state.isRefetching === true;
4580
4661
  if (!initialized) {
@@ -4583,6 +4664,7 @@ function createAuthClient(options) {
4583
4664
  return;
4584
4665
  }
4585
4666
  const settled = betterAuthRefetching && !refetching;
4667
+ if (refetching && !betterAuthRefetching) transportSequence = betterAuthTransportSequence;
4586
4668
  betterAuthRefetching = refetching;
4587
4669
  if (refetching && signOutRequest) suppressBetterAuthSettlement = true;
4588
4670
  if (!settled) return;
@@ -4590,6 +4672,7 @@ function createAuthClient(options) {
4590
4672
  suppressBetterAuthSettlement = false;
4591
4673
  return;
4592
4674
  }
4675
+ if (transportSequence !== betterAuthTransportSequence) return;
4593
4676
  queueSignalRefresh();
4594
4677
  });
4595
4678
  }
@@ -4610,13 +4693,14 @@ function createAuthClient(options) {
4610
4693
  signalRefreshRequest = request;
4611
4694
  }
4612
4695
  function clearCredential() {
4696
+ userApiCredentials.clear();
4613
4697
  credential = void 0;
4614
4698
  credentialRequests.clear();
4615
4699
  selectedWorkspaceKey = void 0;
4616
4700
  credentialGeneration += 1;
4617
4701
  }
4618
4702
  function updateSession(session) {
4619
- const unboundCredential = !sessionId && (credential || credentialRequests.size > 0);
4703
+ const unboundCredential = !sessionId && (credential || credentialRequests.size > 0 || userApiCredentials.hasAuthority());
4620
4704
  const changedSession = sessionId === void 0 ? !sessionAuthorityObserved || session !== null : !session || session.id !== sessionId || session.user.id !== sessionUserId;
4621
4705
  if (!session || unboundCredential || sessionId && (session.id !== sessionId || session.user.id !== sessionUserId)) clearCredential();
4622
4706
  if (changedSession || recentAuthenticationStartAttempt && (recentAuthenticationStartAttempt.sessionId !== session?.id || recentAuthenticationStartAttempt.userId !== session?.user.id)) recentAuthenticationStartAttempt = void 0;
@@ -4626,24 +4710,35 @@ function createAuthClient(options) {
4626
4710
  sessionUserId = session?.user.id;
4627
4711
  return session;
4628
4712
  }
4629
- async function refreshAuthoritySession(generation) {
4713
+ async function readAuthoritySession(generation, request) {
4630
4714
  const readEpoch = ++sessionReadEpoch;
4631
4715
  try {
4632
- const response = await requestJsonResponse(joinURL(authOrigin, "api/v1/auth/get-session"), {
4716
+ const response = await requestJsonResponse(request?.url ?? joinURL(authOrigin, "api/v1/auth/get-session"), {
4633
4717
  fetch: fetchImpl,
4634
4718
  timeoutMs,
4635
- method: "GET"
4719
+ method: "GET",
4720
+ ...request ? {
4721
+ headers: request.headers,
4722
+ signal: request.signal
4723
+ } : {}
4636
4724
  });
4637
4725
  if (generation !== authorityGeneration || readEpoch !== sessionReadEpoch) throw new AuthError("state_conflict", 409);
4638
- return acceptAuthoritySession(normalizeSession(response.value), generation);
4726
+ return {
4727
+ ...response,
4728
+ session: acceptAuthoritySession(normalizeSession(response.value), generation)
4729
+ };
4639
4730
  } catch (error) {
4640
4731
  if (generation !== authorityGeneration || readEpoch !== sessionReadEpoch) throw new AuthError("state_conflict", 409);
4641
4732
  if (error instanceof AuthError && error.code === "state_conflict") throw error;
4642
- unavailable();
4733
+ if (error instanceof AuthError && error.status === 401) acceptAuthoritySession(null, generation);
4734
+ else unavailable();
4643
4735
  if (error instanceof AuthError) throw error;
4644
4736
  throw authorityUnavailable();
4645
4737
  }
4646
4738
  }
4739
+ async function refreshAuthoritySession(generation) {
4740
+ return (await readAuthoritySession(generation)).session;
4741
+ }
4647
4742
  function getSession() {
4648
4743
  if (signOutRequest || activeAccountMutationGeneration !== void 0) return Promise.reject(new AuthError("state_conflict", 409));
4649
4744
  return refreshAuthoritySession(authorityGeneration);
@@ -5174,6 +5269,10 @@ function createAuthClient(options) {
5174
5269
  }));
5175
5270
  },
5176
5271
  signOut,
5272
+ getUserApiCredential(input) {
5273
+ if (invitationRequest || signOutRequest || activeAccountMutationGeneration !== void 0) return Promise.reject(new AuthError("state_conflict", 409));
5274
+ return userApiCredentials.get(input);
5275
+ },
5177
5276
  getDriveCredential(input) {
5178
5277
  let workspace;
5179
5278
  try {
package/dist/server.d.ts CHANGED
@@ -1,4 +1,27 @@
1
- import { A as PersonalWorkspaceSelection, C as OrganizationPage, D as OrganizationTeamMemberPage, E as OrganizationTeamDisplay, G as SocialIdTokenProvider, K as UpdateOrganizationDisplayInput, O as OrganizationTeamPage, Q as AuthErrorStatus, R as ReceivedOrganizationInvitation, S as OrganizationMemberPage, T as OrganizationTeam, V as ResentOrganizationInvitation, W as SocialIdTokenInput, X as AuthError, Y as WorkspaceSelection, Z as AuthErrorCode, _ as OrganizationDisplay, b as OrganizationMember, c as AuthUser, d as CreatedOrganizationMemberInvitation, f as CreatedOrganizationTeam, g as InvitationAcceptance, k as OrganizationWorkspaceSelection, l as CanceledOrganizationInvitation, m as DriveCredentialInput, o as AuthSession, p as DriveCredential, q as UpdateOrganizationTeamDisplayInput, r as AuthOrganization, t as AcceptInvitationInput, u as CreateOrganizationMemberInvitationInput, v as OrganizationInvitation, w as OrganizationPageInput, x as OrganizationMemberAuthority, y as OrganizationInvitationPage, z as ReceivedOrganizationInvitationPage } from "./types-Dpy17xNC.js";
1
+ import { $ as UserApiCredential, A as PersonalWorkspaceSelection, C as OrganizationPage, D as OrganizationTeamMemberPage, E as OrganizationTeamDisplay, G as SocialIdTokenProvider, K as UpdateOrganizationDisplayInput, O as OrganizationTeamPage, Q as AuthErrorStatus, R as ReceivedOrganizationInvitation, S as OrganizationMemberPage, T as OrganizationTeam, V as ResentOrganizationInvitation, W as SocialIdTokenInput, X as AuthError, Y as WorkspaceSelection, Z as AuthErrorCode, _ as OrganizationDisplay, b as OrganizationMember, c as AuthUser, d as CreatedOrganizationMemberInvitation, et as UserApiCredentialInput, f as CreatedOrganizationTeam, g as InvitationAcceptance, k as OrganizationWorkspaceSelection, l as CanceledOrganizationInvitation, m as DriveCredentialInput, o as AuthSession, p as DriveCredential, q as UpdateOrganizationTeamDisplayInput, r as AuthOrganization, t as AcceptInvitationInput, u as CreateOrganizationMemberInvitationInput, v as OrganizationInvitation, w as OrganizationPageInput, x as OrganizationMemberAuthority, y as OrganizationInvitationPage, z as ReceivedOrganizationInvitationPage } from "./types-CqFT4G95.js";
2
+ //#region src/user-api/verifier.d.ts
3
+ interface UserApiIdentity {
4
+ userId: string;
5
+ sessionId: string;
6
+ applicationId: string;
7
+ issuedAt: Date;
8
+ expiresAt: Date;
9
+ user: AuthUser;
10
+ }
11
+ interface UserApiVerifierOptions {
12
+ issuer: string;
13
+ jwksUrl: string;
14
+ audience: string;
15
+ applicationId: string;
16
+ environment: "local" | "development" | "staging" | "production";
17
+ fetch?: typeof globalThis.fetch;
18
+ now?: () => number;
19
+ }
20
+ /** One configured verifier can be shared. It retains public keys, never user authority. */
21
+ declare function createUserApiVerifier(options: UserApiVerifierOptions): {
22
+ verify(token: string): Promise<UserApiIdentity>;
23
+ };
24
+ //#endregion
2
25
  //#region src/identity-resolution.d.ts
3
26
  interface IdentityResolverAuthOptions {
4
27
  authOrigin: string;
@@ -94,8 +117,9 @@ interface FinuevaServerAuth {
94
117
  getReceivedInvitation(invitationId: string): Promise<ReceivedOrganizationInvitation>;
95
118
  signInWithSocialIdToken(input: SocialIdTokenInput): Promise<ServerSocialIdTokenSession>;
96
119
  getDriveCredential(input: DriveCredentialInput): Promise<DriveCredential>;
120
+ getUserApiCredential(input: UserApiCredentialInput): Promise<UserApiCredential>;
97
121
  signOut(): Promise<ServerSignOutResult>;
98
122
  }
99
123
  declare function createServerAuth(options: ServerAuthOptions): FinuevaServerAuth;
100
124
  //#endregion
101
- export { type AcceptInvitationInput, AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type AuthSession, type AuthUser, type CanceledOrganizationInvitation, type CreateOrganizationMemberInvitationInput, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DriveCredential, type DriveCredentialInput, type DriveProvisioningAuthOptions, type DriveProvisioningCredential, type DriveRecipient, type DriveRecipientAuthOptions, type FinuevaDriveProvisioningAuth, type FinuevaDriveRecipientAuth, type FinuevaIdentityResolverAuth, FinuevaServerAuth, type IdentityResolverAuthOptions, type InvitationAcceptance, 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 ResentOrganizationInvitation, type ResolveDriveRecipientInput, type ResolveIdentityInput, type ResolvedIdentity, ServerAuthOptions, ServerInvitationAcceptance, ServerSignOutResult, ServerSocialIdTokenSession, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type WorkspaceSelection, createDriveProvisioningAuth, createDriveRecipientAuth, createIdentityResolverAuth, createServerAuth };
125
+ export { type AcceptInvitationInput, AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type AuthSession, type AuthUser, type CanceledOrganizationInvitation, type CreateOrganizationMemberInvitationInput, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DriveCredential, type DriveCredentialInput, type DriveProvisioningAuthOptions, type DriveProvisioningCredential, type DriveRecipient, type DriveRecipientAuthOptions, type FinuevaDriveProvisioningAuth, type FinuevaDriveRecipientAuth, type FinuevaIdentityResolverAuth, FinuevaServerAuth, type IdentityResolverAuthOptions, type InvitationAcceptance, 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 ResentOrganizationInvitation, type ResolveDriveRecipientInput, type ResolveIdentityInput, type ResolvedIdentity, 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, createServerAuth, createUserApiVerifier };