@finueva/auth 0.16.1 → 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,6 +4532,13 @@ 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",
@@ -4622,13 +4693,14 @@ function createAuthClient(options) {
4622
4693
  signalRefreshRequest = request;
4623
4694
  }
4624
4695
  function clearCredential() {
4696
+ userApiCredentials.clear();
4625
4697
  credential = void 0;
4626
4698
  credentialRequests.clear();
4627
4699
  selectedWorkspaceKey = void 0;
4628
4700
  credentialGeneration += 1;
4629
4701
  }
4630
4702
  function updateSession(session) {
4631
- const unboundCredential = !sessionId && (credential || credentialRequests.size > 0);
4703
+ const unboundCredential = !sessionId && (credential || credentialRequests.size > 0 || userApiCredentials.hasAuthority());
4632
4704
  const changedSession = sessionId === void 0 ? !sessionAuthorityObserved || session !== null : !session || session.id !== sessionId || session.user.id !== sessionUserId;
4633
4705
  if (!session || unboundCredential || sessionId && (session.id !== sessionId || session.user.id !== sessionUserId)) clearCredential();
4634
4706
  if (changedSession || recentAuthenticationStartAttempt && (recentAuthenticationStartAttempt.sessionId !== session?.id || recentAuthenticationStartAttempt.userId !== session?.user.id)) recentAuthenticationStartAttempt = void 0;
@@ -5197,6 +5269,10 @@ function createAuthClient(options) {
5197
5269
  }));
5198
5270
  },
5199
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
+ },
5200
5276
  getDriveCredential(input) {
5201
5277
  let workspace;
5202
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 };