@absolutejs/auth 0.29.0-beta.0 → 0.29.0-beta.1

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
@@ -13616,6 +13616,58 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
13616
13616
  };
13617
13617
  };
13618
13618
  };
13619
+ } & {
13620
+ [x: string]: {
13621
+ get: {
13622
+ body: unknown;
13623
+ params: {};
13624
+ query: {
13625
+ client_id?: string | undefined;
13626
+ state?: string | undefined;
13627
+ id_token_hint?: string | undefined;
13628
+ post_logout_redirect_uri?: string | undefined;
13629
+ };
13630
+ headers: unknown;
13631
+ response: {
13632
+ 200: Response;
13633
+ 422: {
13634
+ type: "validation";
13635
+ on: string;
13636
+ summary?: string;
13637
+ message?: string;
13638
+ found?: unknown;
13639
+ property?: string;
13640
+ expected?: string;
13641
+ };
13642
+ };
13643
+ };
13644
+ };
13645
+ } & {
13646
+ [x: string]: {
13647
+ post: {
13648
+ body: {
13649
+ client_id?: string | undefined;
13650
+ state?: string | undefined;
13651
+ id_token_hint?: string | undefined;
13652
+ post_logout_redirect_uri?: string | undefined;
13653
+ };
13654
+ params: {};
13655
+ query: unknown;
13656
+ headers: unknown;
13657
+ response: {
13658
+ 200: Response;
13659
+ 422: {
13660
+ type: "validation";
13661
+ on: string;
13662
+ summary?: string;
13663
+ message?: string;
13664
+ found?: unknown;
13665
+ property?: string;
13666
+ expected?: string;
13667
+ };
13668
+ };
13669
+ };
13670
+ };
13619
13671
  } & {
13620
13672
  [x: string]: {
13621
13673
  get: {
@@ -13647,7 +13699,7 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
13647
13699
  query: unknown;
13648
13700
  headers: unknown;
13649
13701
  response: {
13650
- 200: Record<string, string | string[]>;
13702
+ 200: Record<string, string | boolean | string[]>;
13651
13703
  };
13652
13704
  };
13653
13705
  };
@@ -14848,8 +14900,9 @@ export { generateSigningKey, jwkThumbprint, signJwt, toPublicJwk, verifyJwt } fr
14848
14900
  export type { SigningKey } from './oidc/keys';
14849
14901
  export { verifyDpopProof } from './oidc/dpop';
14850
14902
  export type { DpopResult } from './oidc/dpop';
14851
- export { createInMemoryAuthorizationCodeStore, createInMemoryDeviceAuthorizationStore, createInMemoryOAuthClientStore, createInMemoryOidcRefreshTokenStore } from './oidc/inMemoryStores';
14852
- export { createNeonAuthorizationCodeStore, createNeonDeviceAuthorizationStore, createNeonOAuthClientStore, createNeonOidcRefreshTokenStore, createPostgresAuthorizationCodeStore, createPostgresDeviceAuthorizationStore, createPostgresOAuthClientStore, createPostgresOidcRefreshTokenStore, oauthClientsTable, oauthCodesTable, oauthDeviceAuthorizationsTable, oauthRefreshTokensTable } from './oidc/postgresStores';
14903
+ export { createInMemoryAuthorizationCodeStore, createInMemoryDeviceAuthorizationStore, createInMemoryLogoutDeliveryStore, createInMemoryOAuthClientStore, createInMemoryOidcRefreshTokenStore } from './oidc/inMemoryStores';
14904
+ export { fanOutBackchannelLogout, mintLogoutToken, resolvePostLogoutRedirect, verifyIdTokenHint } from './oidc/logout';
14905
+ export { createNeonAuthorizationCodeStore, createNeonDeviceAuthorizationStore, createNeonLogoutDeliveryStore, createNeonOAuthClientStore, createNeonOidcRefreshTokenStore, createPostgresAuthorizationCodeStore, createPostgresDeviceAuthorizationStore, createPostgresLogoutDeliveryStore, createPostgresOAuthClientStore, createPostgresOidcRefreshTokenStore, oauthClientsTable, oauthCodesTable, oauthDeviceAuthorizationsTable, oauthLogoutDeliveriesTable, oauthRefreshTokensTable } from './oidc/postgresStores';
14853
14906
  export * from './adaptive/config';
14854
14907
  export * from './adaptive/fingerprint';
14855
14908
  export * from './adaptive/types';
package/dist/index.js CHANGED
@@ -4496,6 +4496,138 @@ var verifyDpopProof = async ({
4496
4496
  return { jkt: await jwkThumbprint(header.jwk), jti };
4497
4497
  };
4498
4498
 
4499
+ // src/oidc/logout.ts
4500
+ var BACKCHANNEL_LOGOUT_EVENT = "http://schemas.openid.net/event/backchannel-logout";
4501
+ var buildLogoutClaims = ({
4502
+ clientId,
4503
+ issuer,
4504
+ now,
4505
+ sub
4506
+ }) => ({
4507
+ aud: clientId,
4508
+ events: { [BACKCHANNEL_LOGOUT_EVENT]: {} },
4509
+ iat: Math.floor(now / MILLISECONDS_IN_A_SECOND),
4510
+ iss: issuer,
4511
+ jti: crypto.randomUUID(),
4512
+ sub
4513
+ });
4514
+ var resolvePostLogoutRedirect = ({
4515
+ client,
4516
+ requestedUri
4517
+ }) => {
4518
+ if (requestedUri === undefined)
4519
+ return;
4520
+ const allow = client.postLogoutRedirectUris ?? [];
4521
+ return allow.includes(requestedUri) ? requestedUri : undefined;
4522
+ };
4523
+ var verifyIdTokenHint = async ({
4524
+ config,
4525
+ idTokenHint
4526
+ }) => {
4527
+ const verified = await verifyJwt(idTokenHint, config.signingKey.publicJwk);
4528
+ const payload = verified?.payload;
4529
+ if (payload === undefined || typeof payload.sub !== "string" || typeof payload.aud !== "string" || payload.iss !== config.issuer) {
4530
+ return;
4531
+ }
4532
+ return { audClientId: payload.aud, sub: payload.sub };
4533
+ };
4534
+ var BACKCHANNEL_TIMEOUT_SECONDS = 5;
4535
+ var DEFAULT_BACKCHANNEL_TIMEOUT_MS = BACKCHANNEL_TIMEOUT_SECONDS * MILLISECONDS_IN_A_SECOND;
4536
+ var errorMessage = (error) => error instanceof Error ? error.message : String(error);
4537
+ var statusFromError = (error) => {
4538
+ if (!(error instanceof Error))
4539
+ return;
4540
+ const match = /returned (\d+)/.exec(error.message);
4541
+ return match?.[1] === undefined ? undefined : Number(match[1]);
4542
+ };
4543
+ var mintLogoutToken = async ({
4544
+ clientId,
4545
+ config,
4546
+ now = Date.now(),
4547
+ sub
4548
+ }) => signJwt(buildLogoutClaims({ clientId, issuer: config.issuer, now, sub }), config.signingKey);
4549
+ var postLogoutToken = async ({
4550
+ endpointUrl,
4551
+ fetchImpl,
4552
+ logoutToken,
4553
+ timeoutMs
4554
+ }) => {
4555
+ const response = await fetchImpl(endpointUrl, {
4556
+ body: new URLSearchParams({ logout_token: logoutToken }).toString(),
4557
+ headers: {
4558
+ "content-type": "application/x-www-form-urlencoded"
4559
+ },
4560
+ method: "POST",
4561
+ signal: AbortSignal.timeout(timeoutMs)
4562
+ });
4563
+ if (!response.ok) {
4564
+ throw new Error(`Back-channel logout returned ${response.status}`);
4565
+ }
4566
+ };
4567
+ var deliverLogoutToOne = async ({
4568
+ clientId,
4569
+ config,
4570
+ endpointUrl,
4571
+ fetchImpl,
4572
+ logoutToken,
4573
+ onError,
4574
+ timeoutMs,
4575
+ userId
4576
+ }) => {
4577
+ try {
4578
+ await postLogoutToken({ endpointUrl, fetchImpl, logoutToken, timeoutMs });
4579
+ } catch (error) {
4580
+ const delivery = {
4581
+ attempts: 1,
4582
+ clientId,
4583
+ createdAt: Date.now(),
4584
+ endpointUrl,
4585
+ id: crypto.randomUUID(),
4586
+ lastError: errorMessage(error),
4587
+ lastStatus: statusFromError(error),
4588
+ logoutToken,
4589
+ userId
4590
+ };
4591
+ await config.logoutDeliveryStore?.recordFailure(delivery);
4592
+ await onError?.(delivery);
4593
+ }
4594
+ };
4595
+ var fanOutBackchannelLogout = async ({
4596
+ config,
4597
+ fetchImpl = globalThis.fetch,
4598
+ now = Date.now(),
4599
+ onError,
4600
+ skipClientId,
4601
+ timeoutMs = DEFAULT_BACKCHANNEL_TIMEOUT_MS,
4602
+ userId
4603
+ }) => {
4604
+ const clientIds = await config.refreshTokenStore.listClientIdsForUser(userId);
4605
+ const targets = await Promise.all(clientIds.filter((clientId) => clientId !== skipClientId).map(async (clientId) => {
4606
+ const client = await config.clientStore.findClient(clientId);
4607
+ return client?.backchannelLogoutUri === undefined ? undefined : { client, endpointUrl: client.backchannelLogoutUri };
4608
+ }));
4609
+ const reachable = targets.filter((target) => target !== undefined);
4610
+ await Promise.all(reachable.map(async ({ client, endpointUrl }) => {
4611
+ const logoutToken = await mintLogoutToken({
4612
+ clientId: client.clientId,
4613
+ config,
4614
+ now,
4615
+ sub: userId
4616
+ });
4617
+ await deliverLogoutToOne({
4618
+ clientId: client.clientId,
4619
+ config,
4620
+ endpointUrl,
4621
+ fetchImpl,
4622
+ logoutToken,
4623
+ onError,
4624
+ timeoutMs,
4625
+ userId
4626
+ });
4627
+ }));
4628
+ return reachable.map(({ client }) => client.clientId);
4629
+ };
4630
+
4499
4631
  // src/oidc/routes.ts
4500
4632
  var HTTP_OK2 = 200;
4501
4633
  var HTTP_BAD_REQUEST2 = 400;
@@ -4549,6 +4681,7 @@ var oidcProviderRoutes = (config) => {
4549
4681
  const revokeRoute = `${oidcRoute}/revoke`;
4550
4682
  const deviceAuthorizationRoute = `${oidcRoute}/device_authorization`;
4551
4683
  const deviceApproveRoute = `${oidcRoute}/device/decision`;
4684
+ const endSessionRoute = `${oidcRoute}/end_session`;
4552
4685
  const tokenUrl = `${issuer}${oidcRoute}/token`;
4553
4686
  const authenticateClient = async (clientId, clientSecret) => {
4554
4687
  const client = await clientStore.findClient(clientId);
@@ -4692,8 +4825,11 @@ var oidcProviderRoutes = (config) => {
4692
4825
  }
4693
4826
  const discovery = {
4694
4827
  authorization_endpoint: `${issuer}${authorizeRoute}`,
4828
+ backchannel_logout_session_supported: false,
4829
+ backchannel_logout_supported: true,
4695
4830
  code_challenge_methods_supported: ["S256"],
4696
4831
  dpop_signing_alg_values_supported: ["ES256"],
4832
+ end_session_endpoint: `${issuer}${endSessionRoute}`,
4697
4833
  grant_types_supported: grantTypes,
4698
4834
  id_token_signing_alg_values_supported: ["ES256"],
4699
4835
  introspection_endpoint: `${issuer}${introspectRoute}`,
@@ -4712,6 +4848,47 @@ var oidcProviderRoutes = (config) => {
4712
4848
  if (config.deviceAuthorizationStore) {
4713
4849
  discovery.device_authorization_endpoint = `${issuer}${deviceAuthorizationRoute}`;
4714
4850
  }
4851
+ const handleEndSession = async ({
4852
+ cookie,
4853
+ inMemorySession,
4854
+ query
4855
+ }) => {
4856
+ const hint = query.id_token_hint === undefined ? undefined : await verifyIdTokenHint({
4857
+ config,
4858
+ idTokenHint: query.id_token_hint
4859
+ });
4860
+ const clientId = hint?.audClientId ?? query.client_id;
4861
+ const client = clientId === undefined ? undefined : await config.clientStore.findClient(clientId);
4862
+ const userSession = await loadSessionFromSource({
4863
+ authSessionStore,
4864
+ session: inMemorySession,
4865
+ userSessionId: cookie.value
4866
+ });
4867
+ const resolvedSub = hint?.sub ?? (userSession === undefined ? undefined : getUserId(userSession.user));
4868
+ await clearSession({
4869
+ authSessionStore,
4870
+ cookie,
4871
+ inMemorySession
4872
+ });
4873
+ if (resolvedSub !== undefined) {
4874
+ await fanOutBackchannelLogout({
4875
+ config,
4876
+ skipClientId: clientId,
4877
+ userId: resolvedSub
4878
+ });
4879
+ }
4880
+ const redirectUri = client === undefined ? undefined : resolvePostLogoutRedirect({
4881
+ client,
4882
+ requestedUri: query.post_logout_redirect_uri
4883
+ });
4884
+ if (redirectUri === undefined) {
4885
+ return jsonResponse({ ok: true }, HTTP_OK2);
4886
+ }
4887
+ const url = new URL(redirectUri);
4888
+ if (query.state !== undefined)
4889
+ url.searchParams.set("state", query.state);
4890
+ return redirectTo(url.toString());
4891
+ };
4715
4892
  return new Elysia15().use(sessionStore()).get(authorizeRoute, async ({ cookie: { user_session_id }, query, request, store }) => {
4716
4893
  const {
4717
4894
  client_id: clientId,
@@ -4944,6 +5121,42 @@ var oidcProviderRoutes = (config) => {
4944
5121
  cookie: t12.Cookie({
4945
5122
  user_session_id: t12.Optional(userSessionIdTypebox)
4946
5123
  })
5124
+ }).get(endSessionRoute, async ({
5125
+ cookie: { user_session_id },
5126
+ query,
5127
+ store
5128
+ }) => handleEndSession({
5129
+ cookie: user_session_id,
5130
+ inMemorySession: store.session,
5131
+ query
5132
+ }), {
5133
+ cookie: t12.Cookie({
5134
+ user_session_id: t12.Optional(userSessionIdTypebox)
5135
+ }),
5136
+ query: t12.Object({
5137
+ client_id: t12.Optional(t12.String()),
5138
+ id_token_hint: t12.Optional(t12.String()),
5139
+ post_logout_redirect_uri: t12.Optional(t12.String()),
5140
+ state: t12.Optional(t12.String())
5141
+ })
5142
+ }).post(endSessionRoute, async ({
5143
+ body,
5144
+ cookie: { user_session_id },
5145
+ store
5146
+ }) => handleEndSession({
5147
+ cookie: user_session_id,
5148
+ inMemorySession: store.session,
5149
+ query: body
5150
+ }), {
5151
+ body: t12.Object({
5152
+ client_id: t12.Optional(t12.String()),
5153
+ id_token_hint: t12.Optional(t12.String()),
5154
+ post_logout_redirect_uri: t12.Optional(t12.String()),
5155
+ state: t12.Optional(t12.String())
5156
+ }),
5157
+ cookie: t12.Cookie({
5158
+ user_session_id: t12.Optional(userSessionIdTypebox)
5159
+ })
4947
5160
  }).get(jwksRoute, () => ({ keys: [toPublicJwk(signingKey)] })).get("/.well-known/openid-configuration", () => discovery);
4948
5161
  };
4949
5162
 
@@ -7986,8 +8199,8 @@ var attemptOnce = async ({
7986
8199
  }
7987
8200
  return response.status;
7988
8201
  };
7989
- var errorMessage = (error) => error instanceof Error ? error.message : String(error);
7990
- var statusFromError = (error) => {
8202
+ var errorMessage2 = (error) => error instanceof Error ? error.message : String(error);
8203
+ var statusFromError2 = (error) => {
7991
8204
  if (!(error instanceof Error))
7992
8205
  return;
7993
8206
  const match = /returned (\d+)/.exec(error.message);
@@ -8007,8 +8220,8 @@ var persistFailure = async ({
8007
8220
  createdAt: Date.now(),
8008
8221
  endpointUrl: endpoint.url,
8009
8222
  envelope,
8010
- lastError: errorMessage(lastError),
8011
- lastStatus: statusFromError(lastError)
8223
+ lastError: errorMessage2(lastError),
8224
+ lastStatus: statusFromError2(lastError)
8012
8225
  };
8013
8226
  await deliveryStore.recordFailure(record);
8014
8227
  };
@@ -20083,6 +20296,7 @@ var createPostgresApiKeyStore = (db) => ({
20083
20296
  }
20084
20297
  });
20085
20298
  // src/oidc/inMemoryStores.ts
20299
+ var DEFAULT_LIST_LIMIT = 100;
20086
20300
  var createInMemoryAuthorizationCodeStore = () => {
20087
20301
  const codes = new Map;
20088
20302
  return {
@@ -20123,6 +20337,18 @@ var createInMemoryDeviceAuthorizationStore = () => {
20123
20337
  }
20124
20338
  };
20125
20339
  };
20340
+ var createInMemoryLogoutDeliveryStore = () => {
20341
+ const failures = new Map;
20342
+ return {
20343
+ listFailed: async (limit = DEFAULT_LIST_LIMIT) => Array.from(failures.values()).sort((left, right) => right.createdAt - left.createdAt).slice(0, limit),
20344
+ recordFailure: async (delivery) => {
20345
+ failures.set(delivery.id, delivery);
20346
+ },
20347
+ removeFailure: async (deliveryId) => {
20348
+ failures.delete(deliveryId);
20349
+ }
20350
+ };
20351
+ };
20126
20352
  var createInMemoryOAuthClientStore = (clients) => {
20127
20353
  const registry = new Map(clients.map((client) => [client.clientId, client]));
20128
20354
  return {
@@ -20144,17 +20370,28 @@ var createInMemoryOidcRefreshTokenStore = () => {
20144
20370
  }
20145
20371
  },
20146
20372
  getToken: async (tokenHash) => tokens.get(tokenHash),
20373
+ listClientIdsForUser: async (userId) => {
20374
+ const now = Date.now();
20375
+ const active = Array.from(tokens.values()).filter((token) => token.userId === userId && token.expiresAt > now);
20376
+ return Array.from(new Set(active.map((token) => token.clientId)));
20377
+ },
20147
20378
  saveToken: async (token) => {
20148
20379
  tokens.set(token.tokenHash, { ...token });
20149
20380
  }
20150
20381
  };
20151
20382
  };
20152
20383
  // src/oidc/postgresStores.ts
20384
+ var URL_LENGTH = 2048;
20385
+ var DEFAULT_LIST_LIMIT2 = 100;
20153
20386
  var ID_LENGTH7 = 255;
20154
20387
  var oauthClientsTable = pgTable("auth_oauth_clients", {
20388
+ backchannel_logout_uri: varchar("backchannel_logout_uri", {
20389
+ length: URL_LENGTH
20390
+ }),
20155
20391
  client_id: varchar("client_id", { length: ID_LENGTH7 }).primaryKey(),
20156
20392
  hashed_secret: varchar("hashed_secret", { length: ID_LENGTH7 }),
20157
20393
  name: varchar("name", { length: ID_LENGTH7 }).notNull(),
20394
+ post_logout_redirect_uris: text("post_logout_redirect_uris").array(),
20158
20395
  redirect_uris: text("redirect_uris").array().notNull(),
20159
20396
  scopes: text("scopes").array().notNull()
20160
20397
  });
@@ -20184,6 +20421,17 @@ var oauthDeviceAuthorizationsTable = pgTable("auth_oauth_device_authorizations",
20184
20421
  user_code: varchar("user_code", { length: 16 }).notNull().unique(),
20185
20422
  user_sub: varchar("user_sub", { length: ID_LENGTH7 })
20186
20423
  });
20424
+ var oauthLogoutDeliveriesTable = pgTable("auth_oauth_logout_deliveries", {
20425
+ attempts: bigint("attempts", { mode: "number" }).notNull(),
20426
+ client_id: varchar("client_id", { length: ID_LENGTH7 }).notNull(),
20427
+ created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
20428
+ endpoint_url: varchar("endpoint_url", { length: URL_LENGTH }).notNull(),
20429
+ id: varchar("id", { length: ID_LENGTH7 }).primaryKey(),
20430
+ last_error: text("last_error"),
20431
+ last_status: bigint("last_status", { mode: "number" }),
20432
+ logout_token: text("logout_token").notNull(),
20433
+ user_id: varchar("user_id", { length: ID_LENGTH7 }).notNull()
20434
+ });
20187
20435
  var oauthRefreshTokensTable = pgTable("auth_oauth_refresh_tokens", {
20188
20436
  claims_json: jsonb("claims_json").$type(),
20189
20437
  client_id: varchar("client_id", { length: ID_LENGTH7 }).notNull(),
@@ -20195,12 +20443,25 @@ var oauthRefreshTokensTable = pgTable("auth_oauth_refresh_tokens", {
20195
20443
  user_id: varchar("user_id", { length: ID_LENGTH7 }).notNull()
20196
20444
  });
20197
20445
  var toClient2 = (row) => ({
20446
+ backchannelLogoutUri: row.backchannel_logout_uri ?? undefined,
20198
20447
  clientId: row.client_id,
20199
20448
  hashedSecret: row.hashed_secret ?? undefined,
20200
20449
  name: row.name,
20450
+ postLogoutRedirectUris: row.post_logout_redirect_uris ?? undefined,
20201
20451
  redirectUris: row.redirect_uris,
20202
20452
  scopes: row.scopes
20203
20453
  });
20454
+ var toLogoutDelivery = (row) => ({
20455
+ attempts: row.attempts,
20456
+ clientId: row.client_id,
20457
+ createdAt: row.created_at_ms,
20458
+ endpointUrl: row.endpoint_url,
20459
+ id: row.id,
20460
+ lastError: row.last_error ?? undefined,
20461
+ lastStatus: row.last_status ?? undefined,
20462
+ logoutToken: row.logout_token,
20463
+ userId: row.user_id
20464
+ });
20204
20465
  var toCode = (row) => ({
20205
20466
  claims: row.claims_json ?? undefined,
20206
20467
  clientId: row.client_id,
@@ -20260,6 +20521,7 @@ var toRefreshValues = (token) => ({
20260
20521
  });
20261
20522
  var createNeonAuthorizationCodeStore = (databaseUrl) => createPostgresAuthorizationCodeStore(createNeonDatabase(databaseUrl));
20262
20523
  var createNeonDeviceAuthorizationStore = (databaseUrl) => createPostgresDeviceAuthorizationStore(createNeonDatabase(databaseUrl));
20524
+ var createNeonLogoutDeliveryStore = (databaseUrl) => createPostgresLogoutDeliveryStore(createNeonDatabase(databaseUrl));
20263
20525
  var createNeonOAuthClientStore = (databaseUrl) => createPostgresOAuthClientStore(createNeonDatabase(databaseUrl));
20264
20526
  var createNeonOidcRefreshTokenStore = (databaseUrl) => createPostgresOidcRefreshTokenStore(createNeonDatabase(databaseUrl));
20265
20527
  var createPostgresAuthorizationCodeStore = (db) => ({
@@ -20300,6 +20562,28 @@ var createPostgresDeviceAuthorizationStore = (db) => ({
20300
20562
  await db.update(oauthDeviceAuthorizationsTable).set({ status, user_sub: userSub ?? null }).where(eq(oauthDeviceAuthorizationsTable.device_code_hash, deviceCodeHash));
20301
20563
  }
20302
20564
  });
20565
+ var createPostgresLogoutDeliveryStore = (db) => ({
20566
+ listFailed: async (limit = DEFAULT_LIST_LIMIT2) => {
20567
+ const rows = await db.select().from(oauthLogoutDeliveriesTable).orderBy(desc(oauthLogoutDeliveriesTable.created_at_ms)).limit(limit);
20568
+ return rows.map(toLogoutDelivery);
20569
+ },
20570
+ recordFailure: async (delivery) => {
20571
+ await db.insert(oauthLogoutDeliveriesTable).values({
20572
+ attempts: delivery.attempts,
20573
+ client_id: delivery.clientId,
20574
+ created_at_ms: delivery.createdAt,
20575
+ endpoint_url: delivery.endpointUrl,
20576
+ id: delivery.id,
20577
+ last_error: delivery.lastError ?? null,
20578
+ last_status: delivery.lastStatus ?? null,
20579
+ logout_token: delivery.logoutToken,
20580
+ user_id: delivery.userId
20581
+ });
20582
+ },
20583
+ removeFailure: async (deliveryId) => {
20584
+ await db.delete(oauthLogoutDeliveriesTable).where(eq(oauthLogoutDeliveriesTable.id, deliveryId));
20585
+ }
20586
+ });
20303
20587
  var createPostgresOAuthClientStore = (db) => ({
20304
20588
  findClient: async (clientId) => {
20305
20589
  const [row] = await db.select().from(oauthClientsTable).where(eq(oauthClientsTable.client_id, clientId)).limit(1);
@@ -20318,6 +20602,10 @@ var createPostgresOidcRefreshTokenStore = (db) => ({
20318
20602
  const [row] = await db.select().from(oauthRefreshTokensTable).where(eq(oauthRefreshTokensTable.token_hash, tokenHash)).limit(1);
20319
20603
  return row ? toRefresh(row) : undefined;
20320
20604
  },
20605
+ listClientIdsForUser: async (userId) => {
20606
+ const rows = await db.selectDistinct({ client_id: oauthRefreshTokensTable.client_id }).from(oauthRefreshTokensTable).where(and(eq(oauthRefreshTokensTable.user_id, userId), gt(oauthRefreshTokensTable.expires_at_ms, Date.now())));
20607
+ return rows.map((row) => row.client_id);
20608
+ },
20321
20609
  saveToken: async (token) => {
20322
20610
  await db.insert(oauthRefreshTokensTable).values(toRefreshValues(token));
20323
20611
  }
@@ -21451,11 +21739,11 @@ var createPostgresPasswordlessTokenStore = (db) => ({
21451
21739
  }
21452
21740
  });
21453
21741
  // src/webhooks/inMemoryStore.ts
21454
- var DEFAULT_LIST_LIMIT = 100;
21742
+ var DEFAULT_LIST_LIMIT3 = 100;
21455
21743
  var createInMemoryWebhookDeliveryStore = () => {
21456
21744
  const failures = new Map;
21457
21745
  return {
21458
- listFailed: async (limit = DEFAULT_LIST_LIMIT) => Array.from(failures.values()).sort((left, right) => right.createdAt - left.createdAt).slice(0, limit),
21746
+ listFailed: async (limit = DEFAULT_LIST_LIMIT3) => Array.from(failures.values()).sort((left, right) => right.createdAt - left.createdAt).slice(0, limit),
21459
21747
  recordFailure: async (delivery) => {
21460
21748
  failures.set(delivery.envelope.id, delivery);
21461
21749
  },
@@ -21466,12 +21754,12 @@ var createInMemoryWebhookDeliveryStore = () => {
21466
21754
  };
21467
21755
  // src/webhooks/postgresStore.ts
21468
21756
  var ID_LENGTH15 = 255;
21469
- var URL_LENGTH = 2048;
21470
- var DEFAULT_LIST_LIMIT2 = 100;
21757
+ var URL_LENGTH2 = 2048;
21758
+ var DEFAULT_LIST_LIMIT4 = 100;
21471
21759
  var webhookDeliveriesTable = pgTable("auth_webhook_deliveries", {
21472
21760
  attempts: bigint("attempts", { mode: "number" }).notNull(),
21473
21761
  created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
21474
- endpoint_url: varchar("endpoint_url", { length: URL_LENGTH }).notNull(),
21762
+ endpoint_url: varchar("endpoint_url", { length: URL_LENGTH2 }).notNull(),
21475
21763
  envelope_id: varchar("envelope_id", { length: ID_LENGTH15 }).primaryKey(),
21476
21764
  envelope_json: jsonb("envelope_json").$type().notNull(),
21477
21765
  last_error: text("last_error"),
@@ -21487,7 +21775,7 @@ var toDelivery = (row) => ({
21487
21775
  });
21488
21776
  var createNeonWebhookDeliveryStore = (databaseUrl) => createPostgresWebhookDeliveryStore(createNeonDatabase(databaseUrl));
21489
21777
  var createPostgresWebhookDeliveryStore = (db) => ({
21490
- listFailed: async (limit = DEFAULT_LIST_LIMIT2) => {
21778
+ listFailed: async (limit = DEFAULT_LIST_LIMIT4) => {
21491
21779
  const rows = await db.select().from(webhookDeliveriesTable).orderBy(desc(webhookDeliveriesTable.created_at_ms)).limit(limit);
21492
21780
  return rows.map(toDelivery);
21493
21781
  },
@@ -21742,6 +22030,7 @@ export {
21742
22030
  verifyPkce,
21743
22031
  verifyPassword,
21744
22032
  verifyJwt,
22033
+ verifyIdTokenHint,
21745
22034
  verifyHcaptcha,
21746
22035
  verifyDpopProof,
21747
22036
  verifyAuditChain,
@@ -21780,6 +22069,7 @@ export {
21780
22069
  resolveSetupSession,
21781
22070
  resolveScimOrganization,
21782
22071
  resolveProviderClientConfiguration,
22072
+ resolvePostLogoutRedirect,
21783
22073
  resolvePermissions,
21784
22074
  resolveOAuthTokenExpiresAt,
21785
22075
  resolveOAuthAuthorization,
@@ -21807,9 +22097,11 @@ export {
21807
22097
  oidcProviderRoutes,
21808
22098
  oidcProviderOptions,
21809
22099
  oauthRefreshTokensTable,
22100
+ oauthLogoutDeliveriesTable,
21810
22101
  oauthDeviceAuthorizationsTable,
21811
22102
  oauthCodesTable,
21812
22103
  oauthClientsTable,
22104
+ mintLogoutToken,
21813
22105
  mfaTotpRoutes,
21814
22106
  mfaRoutes,
21815
22107
  mfaEnrollmentsTable,
@@ -21858,6 +22150,7 @@ export {
21858
22150
  generateEncryptionKey,
21859
22151
  generateBackupCodes,
21860
22152
  fingerprintDevice,
22153
+ fanOutBackchannelLogout,
21861
22154
  extractPropFromIdentity,
21862
22155
  exportAuditCsv,
21863
22156
  exchangeToken,
@@ -21909,6 +22202,7 @@ export {
21909
22202
  createPostgresOidcRefreshTokenStore,
21910
22203
  createPostgresOAuthClientStore,
21911
22204
  createPostgresMfaStore,
22205
+ createPostgresLogoutDeliveryStore,
21912
22206
  createPostgresLoginHistoryStore,
21913
22207
  createPostgresLockoutStore,
21914
22208
  createPostgresKnownDeviceStore,
@@ -21935,6 +22229,7 @@ export {
21935
22229
  createNeonOAuthLinkedProviderCredentialResolver,
21936
22230
  createNeonOAuthClientStore,
21937
22231
  createNeonMfaStore,
22232
+ createNeonLogoutDeliveryStore,
21938
22233
  createNeonLoginHistoryStore,
21939
22234
  createNeonLockoutStore,
21940
22235
  createNeonLinkedProviderStores,
@@ -21965,6 +22260,7 @@ export {
21965
22260
  createInMemoryOidcRefreshTokenStore,
21966
22261
  createInMemoryOAuthClientStore,
21967
22262
  createInMemoryMfaStore,
22263
+ createInMemoryLogoutDeliveryStore,
21968
22264
  createInMemoryLoginHistoryStore,
21969
22265
  createInMemoryLockoutStore,
21970
22266
  createInMemoryLinkedProviderStores,
@@ -22039,5 +22335,5 @@ export {
22039
22335
  AuthIdentityConflictError
22040
22336
  };
22041
22337
 
22042
- //# debugId=451C9751C02E5E2164756E2164756E21
22338
+ //# debugId=9518CC46948D590564756E2164756E21
22043
22339
  //# sourceMappingURL=index.js.map