@absolutejs/auth 0.49.3 → 0.51.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/index.d.ts CHANGED
@@ -12,7 +12,7 @@ import { AuthConfig } from './types';
12
12
  * `UserType`); the routes are reached by path at runtime / direct fetch. */
13
13
  type MergeAuthContext<Base, Extra> = Base extends Elysia<infer Path, infer Singleton, infer Definitions, infer Metadata, infer Routes, infer Ephemeral, infer Volatile> ? Extra extends Elysia<infer ExtraPath, infer ExtraSingleton, infer ExtraDefinitions, infer ExtraMetadata, infer ExtraRoutes, infer ExtraEphemeral, infer ExtraVolatile> ? Elysia<Path & ExtraPath, Singleton & ExtraSingleton, Definitions & ExtraDefinitions, Metadata & ExtraMetadata, Routes & ExtraRoutes, Ephemeral & ExtraEphemeral, Volatile & ExtraVolatile> : never : never;
14
14
  export type AuthInstance<UserType> = MergeAuthContext<ReturnType<typeof protectRoutePlugin<UserType>>, ReturnType<typeof stepUpPlugin<UserType>>>;
15
- export declare const auth: <UserType>({ providersConfiguration, authorizeRoute, cookieSecure, callbackRoute, profileRoute, signoutRoute, statusRoute, refreshRoute, revokeRoute, cleanupIntervalMs, maxSessions, sessionDurationMs, authSessionStore, audit, credentials, mfa, passwordless, lockout, sessions, sso, scim, apikeys, oidc, organizations, roles, portal, authorization, compliance, webauthn, webhooks, htmx, tracing, resolveAuthIntent, onAuthorizeSuccess, onAuthorizeError, onProfileSuccess, onProfileError, onCallbackSuccess, onLinkIdentity, onLinkIdentityConflict, onLinkConnector, onCallbackError, onStatus, onRefreshSuccess, onRefreshError, onSignOut, onRevocationSuccess, onRevocationError, onSessionCleanup }: AuthConfig<UserType>) => Promise<Elysia<"", {
15
+ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute, cookieSecure, callbackRoute, profileRoute, signoutRoute, statusRoute, refreshRoute, revokeRoute, cleanupIntervalMs, maxSessions, sessionDurationMs, authSessionStore, audit, credentials, customProviders, mfa, passwordless, lockout, sessions, sso, scim, apikeys, oidc, organizations, roles, portal, authorization, compliance, webauthn, webhooks, htmx, tracing, resolveAuthIntent, onAuthorizeSuccess, onAuthorizeError, onProfileSuccess, onProfileError, onCallbackSuccess, onLinkIdentity, onLinkIdentityConflict, onLinkConnector, onCallbackError, onStatus, onRefreshSuccess, onRefreshError, onSignOut, onRevocationSuccess, onRevocationError, onSessionCleanup }: AuthConfig<UserType>) => Promise<Elysia<"", {
16
16
  decorator: {};
17
17
  store: {
18
18
  session: import("./types").SessionRecord<UserType>;
@@ -127,8 +127,8 @@ export { resolveAuthHtmxRenderers } from './htmx/renderers';
127
127
  export type { AuthHtmxConfig, AuthHtmxConnectorTarget, AuthHtmxProviderData, AuthHtmxProviderInfo, AuthHtmxRenderOverrides, AuthHtmxRenderersConfig, AuthHtmxUser, AuthIdentityPayload, LinkedProviderPayload } from './htmx/types';
128
128
  export * from './utils';
129
129
  export { buildClientProviders, resolveClientProviderEntry, resolveProviderClientConfiguration } from './providers/clients';
130
- export type { OAuth2TokenResponse, OAuth2Client, ProviderOption, PKCEProvider, OIDCProvider, RefreshableProvider, RevocableProvider, ScopeRequiredProvider, ProvidersMap, ProviderConfiguration, CredentialsFor } from 'citra';
131
- export { providers, providerOptions, refreshableProviderOptions, revocableProviderOptions, oidcProviderOptions, pkceProviderOptions, scopeRequiredProviderOptions, decodeJWT, extractPropFromIdentity, isValidProviderOption, isRefreshableOAuth2Client, isRefreshableProviderOption, isOIDCProviderOption, isPKCEProviderOption, isRevocableProviderOption, isRevocableOAuth2Client } from 'citra';
130
+ export type { OAuth2TokenResponse, OAuth2Client, OAuth2ClientForConfig, CustomProviderCredentials, ProviderConfig, ProviderOption, PKCEProvider, OIDCProvider, RefreshableProvider, RevocableProvider, ScopeRequiredProvider, ProvidersMap, ProviderConfiguration, CredentialsFor } from 'citra';
131
+ export { providers, providerOptions, createCustomOAuth2Client, defineProvider, refreshableProviderOptions, revocableProviderOptions, oidcProviderOptions, pkceProviderOptions, scopeRequiredProviderOptions, decodeJWT, extractPropFromIdentity, isValidProviderOption, isRefreshableOAuth2Client, isRefreshableProviderOption, isOIDCProviderOption, isPKCEProviderOption, isRevocableProviderOption, isRevocableOAuth2Client } from 'citra';
132
132
  export * from './crypto';
133
133
  export * from './tenancy';
134
134
  export * from './credentials/config';
package/dist/index.js CHANGED
@@ -262,6 +262,7 @@ var anilistProfileQuery = `query {
262
262
  }
263
263
  }`;
264
264
  var defineProviders = (providers) => providers;
265
+ var defineProvider = (config) => config;
265
266
  var providers = defineProviders({
266
267
  "42": {
267
268
  authorizationUrl: "https://api.intra.42.fr/oauth/authorize",
@@ -1347,6 +1348,37 @@ var providers = defineProviders({
1347
1348
  url: (config) => `https://${config.domain}/oauth2/default/v1/token`
1348
1349
  }
1349
1350
  },
1351
+ onspark: {
1352
+ authorizationUrl: "https://app.onspark.com/oauth2/authorize",
1353
+ email: ["email"],
1354
+ familyName: ["family_name"],
1355
+ fullName: ["name"],
1356
+ givenName: ["given_name"],
1357
+ isOIDC: true,
1358
+ isRefreshable: true,
1359
+ picture: ["picture"],
1360
+ PKCEMethod: "S256",
1361
+ profileRequest: {
1362
+ authIn: "header",
1363
+ encoding: "application/json",
1364
+ method: "GET",
1365
+ url: "https://app.onspark.com/oauth2/userinfo"
1366
+ },
1367
+ revocationRequest: {
1368
+ authIn: "body",
1369
+ encoding: "application/x-www-form-urlencoded",
1370
+ tokenParamName: "token",
1371
+ url: "https://app.onspark.com/oauth2/revoke"
1372
+ },
1373
+ scopeRequired: true,
1374
+ subject: ["sub"],
1375
+ subjectType: "string",
1376
+ tokenRequest: {
1377
+ authIn: "body",
1378
+ encoding: "application/x-www-form-urlencoded",
1379
+ url: "https://app.onspark.com/oauth2/token"
1380
+ }
1381
+ },
1350
1382
  osu: {
1351
1383
  authorizationUrl: "https://osu.ppy.sh/oauth/authorize",
1352
1384
  isOIDC: false,
@@ -1898,6 +1930,7 @@ var providers = defineProviders({
1898
1930
  method: "POST",
1899
1931
  url: "https://wbsapi.withings.net/v2/oauth2"
1900
1932
  },
1933
+ scopeDelimiter: ",",
1901
1934
  scopeRequired: true,
1902
1935
  subject: ["userid"],
1903
1936
  subjectType: "string",
@@ -2529,8 +2562,7 @@ var refreshableProviderOptions = Object.keys(providers).filter(isRefreshableProv
2529
2562
  var revocableProviderOptions = Object.keys(providers).filter(isRevocableProviderOption);
2530
2563
  var scopeRequiredProviderOptions = Object.keys(providers).filter(isScopeRequiredProviderOption);
2531
2564
  var readPath = (value, path) => path.reduce((cursor, key) => cursor && typeof cursor === "object" ? Reflect.get(cursor, key) : undefined, value);
2532
- var createOAuth2Client = async (providerName, config) => {
2533
- const meta = providers[providerName];
2565
+ var buildOAuth2Client = async (meta, config) => {
2534
2566
  const isConfigPropertyFunction = (cfgProp) => typeof cfgProp === "function";
2535
2567
  const resolveConfigProp = async (cfgProp) => {
2536
2568
  const result = isConfigPropertyFunction(cfgProp) ? cfgProp(config) : cfgProp;
@@ -2549,8 +2581,7 @@ var createOAuth2Client = async (providerName, config) => {
2549
2581
  if (state)
2550
2582
  url.searchParams.set("state", state);
2551
2583
  if (scope.length !== 0) {
2552
- const delimeter = providerName === "withings" ? "," : " ";
2553
- url.searchParams.set(meta.scopeParamName ?? "scope", scope.join(delimeter));
2584
+ url.searchParams.set(meta.scopeParamName ?? "scope", scope.join(meta.scopeDelimiter ?? " "));
2554
2585
  }
2555
2586
  if (meta.PKCEMethod !== undefined) {
2556
2587
  if (!codeVerifier) {
@@ -2732,6 +2763,8 @@ var createOAuth2Client = async (providerName, config) => {
2732
2763
  }
2733
2764
  };
2734
2765
  };
2766
+ var createCustomOAuth2Client = (providerConfig, credentials) => buildOAuth2Client(providerConfig, credentials);
2767
+ var createOAuth2Client = (providerName, config) => buildOAuth2Client(providers[providerName], config);
2735
2768
 
2736
2769
  // src/index.ts
2737
2770
  import { Elysia as Elysia40 } from "elysia";
@@ -3201,7 +3234,7 @@ var authIntentOption = t2.Optional(t2.Union([
3201
3234
  t2.Literal("link_identity"),
3202
3235
  t2.Literal("link_connector")
3203
3236
  ]));
3204
- var authProviderOption = t2.Enum(Object.fromEntries(Object.keys(providers).filter(isValidProviderOption).map((key) => [key, key])));
3237
+ var authProviderOption = t2.String({ minLength: 1 });
3205
3238
  var userSessionIdTypebox = t2.Optional(t2.TemplateLiteral("${string}-${string}-${string}-${string}-${string}"));
3206
3239
 
3207
3240
  // src/authorization/protectPermission.ts
@@ -3273,6 +3306,7 @@ var getStatus = async (session, user_session_id) => {
3273
3306
  };
3274
3307
  var instantiateUserSession = async ({
3275
3308
  authProvider,
3309
+ providerConfiguration,
3276
3310
  cookieSecure,
3277
3311
  session,
3278
3312
  user_session_id,
@@ -3287,6 +3321,7 @@ var instantiateUserSession = async ({
3287
3321
  }) => {
3288
3322
  const authorization = resolvedAuthorization ?? await resolveOAuthAuthorization({
3289
3323
  authProvider,
3324
+ providerConfiguration,
3290
3325
  providerInstance,
3291
3326
  tokenResponse
3292
3327
  });
@@ -3331,23 +3366,28 @@ var instantiateUserSession = async ({
3331
3366
  var resolveCookieSecure = (override) => override ?? false;
3332
3367
  var resolveOAuthAuthorization = async ({
3333
3368
  authProvider,
3369
+ providerConfiguration,
3334
3370
  providerInstance,
3335
3371
  tokenResponse,
3336
3372
  now = Date.now()
3337
3373
  }) => {
3374
+ const meta = providerConfiguration ?? (isValidProviderOption(authProvider) ? providers[authProvider] : undefined);
3375
+ if (!meta) {
3376
+ throw new Error(`No provider configuration for "${authProvider}" \u2014 pass providerConfiguration (custom provider) or resolvedAuthorization`);
3377
+ }
3338
3378
  let userIdentity;
3339
3379
  let accessToken = tokenResponse.access_token;
3340
3380
  let refreshToken = tokenResponse.refresh_token;
3341
3381
  if (tokenResponse.id_token) {
3342
3382
  userIdentity = normalizeProviderIdentity({
3343
3383
  identity: decodeJWT(tokenResponse.id_token),
3344
- providerConfiguration: providers[authProvider],
3384
+ providerConfiguration: meta,
3345
3385
  source: "idToken"
3346
3386
  });
3347
- } else if (providers[authProvider].subjectBySource?.tokenResponse) {
3387
+ } else if (meta.subjectBySource?.tokenResponse) {
3348
3388
  userIdentity = normalizeProviderIdentity({
3349
3389
  identity: tokenResponse,
3350
- providerConfiguration: providers[authProvider],
3390
+ providerConfiguration: meta,
3351
3391
  source: "tokenResponse"
3352
3392
  });
3353
3393
  } else if (authProvider === "withings") {
@@ -3357,7 +3397,7 @@ var resolveOAuthAuthorization = async ({
3357
3397
  } else {
3358
3398
  userIdentity = normalizeProviderIdentity({
3359
3399
  identity: await providerInstance.fetchUserProfile(tokenResponse.access_token),
3360
- providerConfiguration: providers[authProvider],
3400
+ providerConfiguration: meta,
3361
3401
  source: "profile"
3362
3402
  });
3363
3403
  }
@@ -4354,6 +4394,7 @@ var DEFAULT_SMS_CODE_LENGTH = 6;
4354
4394
  var SMS_CODE_TTL_MINUTES = 5;
4355
4395
  var DEFAULT_SMS_CODE_TTL_MS = SMS_CODE_TTL_MINUTES * SECONDS_IN_A_MINUTE * MILLISECONDS_IN_A_SECOND;
4356
4396
  var DEFAULT_SMS_MAX_ATTEMPTS = 3;
4397
+ var DEFAULT_TOTP_MAX_ATTEMPTS = 5;
4357
4398
 
4358
4399
  // src/mfa/secret.ts
4359
4400
  init_crypto();
@@ -4521,7 +4562,8 @@ var mfaChallenge = ({
4521
4562
  sessionDurationMs = DEFAULT_MFA_SESSION_TTL_MS,
4522
4563
  smsCodeLength = DEFAULT_SMS_CODE_LENGTH,
4523
4564
  smsCodeTtlMs = DEFAULT_SMS_CODE_TTL_MS,
4524
- smsMaxAttempts = DEFAULT_SMS_MAX_ATTEMPTS
4565
+ smsMaxAttempts = DEFAULT_SMS_MAX_ATTEMPTS,
4566
+ totpMaxAttempts = DEFAULT_TOTP_MAX_ATTEMPTS
4525
4567
  }) => new Elysia13().use(sessionStore()).post(challengeRoute, async ({
4526
4568
  body: { action, code, factor },
4527
4569
  cookie: { user_session_id },
@@ -4620,12 +4662,24 @@ var mfaChallenge = ({
4620
4662
  if (code === undefined) {
4621
4663
  return status("Unauthorized", "Invalid MFA code");
4622
4664
  }
4665
+ if ((enrollment.totpFailedAttempts ?? 0) >= totpMaxAttempts) {
4666
+ await onMfaChallengeError?.({
4667
+ error: new Error("mfa_totp_attempts_exceeded"),
4668
+ userId: getUserId(user)
4669
+ });
4670
+ return status("Unauthorized", "Too many attempts");
4671
+ }
4623
4672
  const totpValid = enrollment.totpVerified && enrollment.totpSecretCiphertext ? await verifyTotp({
4624
4673
  secret: await decryptTotpSecret(enrollment.totpSecretCiphertext, encryptionKey),
4625
4674
  token: code
4626
4675
  }) : false;
4627
4676
  const remainingBackupHashes = totpValid ? undefined : await consumeBackupCode(code, enrollment.backupCodeHashes);
4628
4677
  if (!totpValid && remainingBackupHashes === undefined) {
4678
+ await mfaStore.saveEnrollment({
4679
+ ...enrollment,
4680
+ totpFailedAttempts: (enrollment.totpFailedAttempts ?? 0) + 1,
4681
+ updatedAt: Date.now()
4682
+ });
4629
4683
  await onMfaChallengeError?.({
4630
4684
  error: new Error("invalid_mfa_code"),
4631
4685
  userId: getUserId(user)
@@ -4636,6 +4690,7 @@ var mfaChallenge = ({
4636
4690
  ...enrollment,
4637
4691
  backupCodeHashes: remainingBackupHashes ?? enrollment.backupCodeHashes,
4638
4692
  lastUsedAt: Date.now(),
4693
+ totpFailedAttempts: 0,
4639
4694
  updatedAt: Date.now()
4640
4695
  });
4641
4696
  return promote();
@@ -8252,7 +8307,52 @@ var roleRoutes = ({
8252
8307
  // src/providers/clients.ts
8253
8308
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
8254
8309
  var isProviderClientConfig = (value) => isRecord(value) && ("credentials" in value);
8255
- var buildClientProviders = async (providersConfiguration, createOAuth2ClientFn) => {
8310
+ var isCustomClientConfig = (value) => isRecord(value) && ("credentials" in value) && ("providerConfig" in value);
8311
+ var normalizeCustomClients = (providerName, providerConfig) => {
8312
+ if (isCustomClientConfig(providerConfig))
8313
+ return { "": providerConfig };
8314
+ if (!isRecord(providerConfig) || Object.keys(providerConfig).length === 0) {
8315
+ throw new Error(`Invalid custom provider configuration for ${providerName}`);
8316
+ }
8317
+ Object.entries(providerConfig).forEach(([clientName, clientConfig]) => {
8318
+ if (!isCustomClientConfig(clientConfig)) {
8319
+ throw new Error(`Invalid custom client configuration for ${providerName}.${clientName}`);
8320
+ }
8321
+ });
8322
+ return providerConfig;
8323
+ };
8324
+ var buildCustomProviderGroups = async (customProviders) => {
8325
+ const groups = await Promise.all(Object.entries(customProviders).map(async ([providerName, config]) => {
8326
+ if (isValidProviderOption(providerName)) {
8327
+ throw new Error(`Custom provider "${providerName}" collides with a built-in provider \u2014 configure it under providersConfiguration instead`);
8328
+ }
8329
+ const clients = normalizeCustomClients(providerName, config);
8330
+ const entries = await Promise.all(Object.entries(clients).map(async ([clientName, clientConfig]) => {
8331
+ const providerInstance = await createCustomOAuth2Client(clientConfig.providerConfig, clientConfig.credentials);
8332
+ return [
8333
+ clientName,
8334
+ {
8335
+ clientName: clientName.length > 0 ? clientName : undefined,
8336
+ providerConfiguration: clientConfig.providerConfig,
8337
+ providerInstance,
8338
+ requiresPKCE: clientConfig.providerConfig.PKCEMethod !== undefined,
8339
+ scope: clientConfig.scope,
8340
+ searchParams: clientConfig.searchParams
8341
+ }
8342
+ ];
8343
+ }));
8344
+ return [
8345
+ providerName,
8346
+ {
8347
+ entries: Object.fromEntries(entries),
8348
+ isSingleClient: entries.length === 1 && entries[0]?.[0] === ""
8349
+ }
8350
+ ];
8351
+ }));
8352
+ return Object.fromEntries(groups);
8353
+ };
8354
+ var buildClientProviders = async (providersConfiguration, createOAuth2ClientFn, customProviders) => {
8355
+ const customGroups = customProviders ? await buildCustomProviderGroups(customProviders) : {};
8256
8356
  const normalized = normalizeProvidersConfiguration(providersConfiguration);
8257
8357
  const groups = await Promise.all(Object.entries(normalized).map(async ([providerName, clients]) => {
8258
8358
  if (!isValidProviderOption(providerName)) {
@@ -8264,7 +8364,9 @@ var buildClientProviders = async (providersConfiguration, createOAuth2ClientFn)
8264
8364
  clientName,
8265
8365
  {
8266
8366
  clientName: clientName.length > 0 ? clientName : undefined,
8367
+ providerConfiguration: providers[providerName],
8267
8368
  providerInstance,
8369
+ requiresPKCE: providers[providerName].PKCEMethod !== undefined,
8268
8370
  scope: providerConfig.scope,
8269
8371
  searchParams: providerConfig.searchParams
8270
8372
  }
@@ -8278,7 +8380,7 @@ var buildClientProviders = async (providersConfiguration, createOAuth2ClientFn)
8278
8380
  }
8279
8381
  ];
8280
8382
  }));
8281
- return Object.fromEntries(groups);
8383
+ return { ...customGroups, ...Object.fromEntries(groups) };
8282
8384
  };
8283
8385
  var normalizeClientConfig = (providerName, clientName, clientConfig) => {
8284
8386
  if (!isProviderClientConfig(clientConfig)) {
@@ -8414,7 +8516,13 @@ var authorize = ({
8414
8516
  if ("error" in resolvedProvider) {
8415
8517
  return status("Unauthorized", resolvedProvider.error);
8416
8518
  }
8417
- const { clientName, providerInstance, scope, searchParams } = resolvedProvider.entry;
8519
+ const {
8520
+ clientName,
8521
+ providerInstance,
8522
+ requiresPKCE,
8523
+ scope,
8524
+ searchParams
8525
+ } = resolvedProvider.entry;
8418
8526
  const referer = parseReferer(headers["referer"]);
8419
8527
  const authIntent = isAuthIntent(intent) ? intent : undefined;
8420
8528
  origin_url.set({
@@ -8462,7 +8570,7 @@ var authorize = ({
8462
8570
  secure,
8463
8571
  value: currentState
8464
8572
  });
8465
- const codeVerifier = isPKCEProviderOption(provider) ? generateCodeVerifier() : undefined;
8573
+ const codeVerifier = requiresPKCE ? generateCodeVerifier() : undefined;
8466
8574
  if (codeVerifier) {
8467
8575
  code_verifier.set({
8468
8576
  httpOnly: true,
@@ -8574,9 +8682,13 @@ var callback = ({
8574
8682
  if ("error" in resolvedProvider) {
8575
8683
  return status("Unauthorized", resolvedProvider.error);
8576
8684
  }
8577
- const { clientName, providerInstance } = resolvedProvider.entry;
8685
+ const {
8686
+ clientName,
8687
+ providerConfiguration,
8688
+ providerInstance,
8689
+ requiresPKCE
8690
+ } = resolvedProvider.entry;
8578
8691
  stored_state.remove();
8579
- const requiresPKCE = isPKCEProviderOption(authProvider);
8580
8692
  const verifier = requiresPKCE ? code_verifier.value : undefined;
8581
8693
  if (requiresPKCE && verifier === undefined) {
8582
8694
  return status("Bad Request", "Code verifier not found and is required");
@@ -8624,6 +8736,7 @@ var callback = ({
8624
8736
  cookie,
8625
8737
  currentUser,
8626
8738
  originUrl,
8739
+ providerConfiguration,
8627
8740
  providerInstance,
8628
8741
  redirect,
8629
8742
  session: callbackSession,
@@ -23203,6 +23316,7 @@ var mfaEnrollmentsTable = pgTable("auth_mfa_enrollments", {
23203
23316
  sms_pending_code_hash: text("sms_pending_code_hash"),
23204
23317
  sms_phone: varchar("sms_phone", { length: PHONE_LENGTH }),
23205
23318
  sms_verified: boolean("sms_verified").notNull().default(false),
23319
+ totp_failed_attempts: smallint("totp_failed_attempts").notNull().default(0),
23206
23320
  totp_secret_ciphertext: text("totp_secret_ciphertext"),
23207
23321
  totp_verified: boolean("totp_verified").notNull().default(false),
23208
23322
  updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull(),
@@ -23217,6 +23331,7 @@ var toEnrollment = (row) => ({
23217
23331
  smsPendingCodeHash: row.sms_pending_code_hash ?? undefined,
23218
23332
  smsPhone: row.sms_phone ?? undefined,
23219
23333
  smsVerified: row.sms_verified,
23334
+ totpFailedAttempts: row.totp_failed_attempts,
23220
23335
  totpSecretCiphertext: row.totp_secret_ciphertext ?? undefined,
23221
23336
  totpVerified: row.totp_verified,
23222
23337
  updatedAt: row.updated_at_ms,
@@ -23245,6 +23360,7 @@ var createPostgresMfaStore = (db) => ({
23245
23360
  sms_pending_code_hash: enrollment.smsPendingCodeHash ?? null,
23246
23361
  sms_phone: enrollment.smsPhone ?? null,
23247
23362
  sms_verified: enrollment.smsVerified,
23363
+ totp_failed_attempts: enrollment.totpFailedAttempts ?? 0,
23248
23364
  totp_secret_ciphertext: enrollment.totpSecretCiphertext ?? null,
23249
23365
  totp_verified: enrollment.totpVerified,
23250
23366
  updated_at_ms: enrollment.updatedAt,
@@ -26573,6 +26689,10 @@ var mfaSmsColumnsMigration = {
26573
26689
  ].join(`
26574
26690
  `)
26575
26691
  };
26692
+ var mfaTotpLockoutMigration = {
26693
+ id: "0003_totp_lockout",
26694
+ sql: 'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "totp_failed_attempts" smallint NOT NULL DEFAULT 0;'
26695
+ };
26576
26696
  var blockMigrations = {
26577
26697
  adaptive: initMigration("adaptive", [knownDevicesTable, loginHistoryTable]),
26578
26698
  apikeys: initMigration("apikeys", [
@@ -26596,7 +26716,8 @@ var blockMigrations = {
26596
26716
  block: "mfa",
26597
26717
  migrations: [
26598
26718
  ...initMigration("mfa", [mfaEnrollmentsTable]).migrations,
26599
- mfaSmsColumnsMigration
26719
+ mfaSmsColumnsMigration,
26720
+ mfaTotpLockoutMigration
26600
26721
  ]
26601
26722
  },
26602
26723
  oidc: initMigration("oidc", [
@@ -27310,6 +27431,7 @@ var auth = async ({
27310
27431
  authSessionStore,
27311
27432
  audit,
27312
27433
  credentials,
27434
+ customProviders,
27313
27435
  mfa,
27314
27436
  passwordless,
27315
27437
  lockout,
@@ -27347,7 +27469,7 @@ var auth = async ({
27347
27469
  }) => {
27348
27470
  if (tracing !== undefined)
27349
27471
  await initTracing(tracing);
27350
- const clientProviders = await buildClientProviders(providersConfiguration, createOAuth2Client);
27472
+ const clientProviders = await buildClientProviders(providersConfiguration, createOAuth2Client, customProviders);
27351
27473
  const resolvedCookieSecure = resolveCookieSecure(cookieSecure);
27352
27474
  const webhookDispatch = webhooks ? createWebhookDispatcher(webhooks) : undefined;
27353
27475
  const auditEmit = audit || webhookDispatch ? createAuditEmitter({
@@ -27677,6 +27799,7 @@ export {
27677
27799
  deleteRegisteredClient,
27678
27800
  defineScimAttributeMap,
27679
27801
  defineProvidersConfiguration,
27802
+ defineProvider,
27680
27803
  defineAuthSettings,
27681
27804
  defineAuthHtmxConfig,
27682
27805
  defineAuthConfig,
@@ -27822,6 +27945,7 @@ export {
27822
27945
  createInMemoryAccessTokenStore,
27823
27946
  createFgaEngine,
27824
27947
  createFederatedTokenStore,
27948
+ createCustomOAuth2Client,
27825
27949
  createCredentialOffer,
27826
27950
  createAuthHtmxRoutes,
27827
27951
  createAuditRedactor,
@@ -27872,6 +27996,7 @@ export {
27872
27996
  DEFAULT_VP_ROUTE,
27873
27997
  DEFAULT_VERIFICATION_TOKEN_TTL_MS,
27874
27998
  DEFAULT_VCI_ROUTE,
27999
+ DEFAULT_TOTP_MAX_ATTEMPTS,
27875
28000
  DEFAULT_TOKEN_ROUTE,
27876
28001
  DEFAULT_STATUS_ROUTE,
27877
28002
  DEFAULT_SSO_SESSION_TTL_MS,
@@ -27903,5 +28028,5 @@ export {
27903
28028
  AuthIdentityConflictError
27904
28029
  };
27905
28030
 
27906
- //# debugId=178CE4DFADBEB75764756E2164756E21
28031
+ //# debugId=CF57DC7D601D3EC464756E2164756E21
27907
28032
  //# sourceMappingURL=index.js.map