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

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.js CHANGED
@@ -4452,6 +4452,105 @@ var exchangeDeviceCode = async ({
4452
4452
  return { ...tokenSet, ok: true };
4453
4453
  };
4454
4454
 
4455
+ // src/oidc/clientAuth.ts
4456
+ var CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
4457
+ var MAX_ASSERTION_LIFETIME_MINUTES = 5;
4458
+ var SECONDS_PER_MINUTE = 60;
4459
+ var MAX_ASSERTION_LIFETIME_MS = MAX_ASSERTION_LIFETIME_MINUTES * SECONDS_PER_MINUTE * MILLISECONDS_IN_A_SECOND;
4460
+ var jwksCache = new Map;
4461
+ var JWKS_CACHE_TTL_MS = SECONDS_PER_MINUTE * MILLISECONDS_IN_A_SECOND;
4462
+ var JWKS_FETCH_TIMEOUT_SECONDS = 5;
4463
+ var JWKS_FETCH_TIMEOUT_MS = JWKS_FETCH_TIMEOUT_SECONDS * MILLISECONDS_IN_A_SECOND;
4464
+ var fetchJwksUri = async (jwksUri) => {
4465
+ const cached = jwksCache.get(jwksUri);
4466
+ if (cached && Date.now() - cached.fetchedAt < JWKS_CACHE_TTL_MS) {
4467
+ return cached.jwks;
4468
+ }
4469
+ try {
4470
+ const response = await fetch(jwksUri, {
4471
+ signal: AbortSignal.timeout(JWKS_FETCH_TIMEOUT_MS)
4472
+ });
4473
+ if (!response.ok)
4474
+ return;
4475
+ const body = await response.json();
4476
+ if (!Array.isArray(body.keys))
4477
+ return;
4478
+ jwksCache.set(jwksUri, { fetchedAt: Date.now(), jwks: body.keys });
4479
+ return body.keys;
4480
+ } catch {
4481
+ return;
4482
+ }
4483
+ };
4484
+ var resolveClientJwks = async (client) => {
4485
+ if (client.jwks && client.jwks.length > 0)
4486
+ return client.jwks;
4487
+ if (client.jwksUri !== undefined)
4488
+ return fetchJwksUri(client.jwksUri);
4489
+ return;
4490
+ };
4491
+ var verifyAgainstAny = async (assertion, candidates) => {
4492
+ for (const jwk of candidates) {
4493
+ const verified = await verifyJwt(assertion, jwk);
4494
+ if (verified !== undefined)
4495
+ return verified;
4496
+ }
4497
+ return;
4498
+ };
4499
+ var verifyClientAssertion = async ({
4500
+ assertion,
4501
+ expectedAudience,
4502
+ jtiStore,
4503
+ resolveClient
4504
+ }) => {
4505
+ const [, payloadSegment] = assertion.split(".");
4506
+ if (payloadSegment === undefined)
4507
+ return;
4508
+ let payload;
4509
+ try {
4510
+ const parsed = JSON.parse(Buffer.from(payloadSegment, "base64url").toString("utf8"));
4511
+ if (typeof parsed !== "object" || parsed === null)
4512
+ return;
4513
+ payload = parsed;
4514
+ } catch {
4515
+ return;
4516
+ }
4517
+ const {
4518
+ aud,
4519
+ exp,
4520
+ iss,
4521
+ jti,
4522
+ sub
4523
+ } = payload;
4524
+ if (typeof iss !== "string" || typeof sub !== "string" || iss !== sub || typeof exp !== "number") {
4525
+ return;
4526
+ }
4527
+ const audMatches = typeof aud === "string" && aud === expectedAudience || Array.isArray(aud) && aud.includes(expectedAudience);
4528
+ if (!audMatches)
4529
+ return;
4530
+ const expMs = exp * MILLISECONDS_IN_A_SECOND;
4531
+ const now = Date.now();
4532
+ if (expMs <= now || expMs - now > MAX_ASSERTION_LIFETIME_MS) {
4533
+ return;
4534
+ }
4535
+ const client = await resolveClient(iss);
4536
+ if (client === undefined)
4537
+ return;
4538
+ const candidates = await resolveClientJwks(client);
4539
+ if (candidates === undefined || candidates.length === 0)
4540
+ return;
4541
+ const verified = await verifyAgainstAny(assertion, candidates);
4542
+ if (verified === undefined)
4543
+ return;
4544
+ if (jtiStore !== undefined) {
4545
+ if (typeof jti !== "string")
4546
+ return;
4547
+ const fresh = await jtiStore.recordIfFresh(client.clientId, jti, expMs);
4548
+ if (!fresh)
4549
+ return;
4550
+ }
4551
+ return client;
4552
+ };
4553
+
4455
4554
  // src/oidc/dpop.ts
4456
4555
  var DEFAULT_MAX_AGE_MS = 60000;
4457
4556
  var SECONDS_TO_MS = 1000;
@@ -4628,11 +4727,218 @@ var fanOutBackchannelLogout = async ({
4628
4727
  return reachable.map(({ client }) => client.clientId);
4629
4728
  };
4630
4729
 
4730
+ // src/oidc/registration.ts
4731
+ var REG_TOKEN_BYTES = 32;
4732
+ var CLIENT_ID_BYTES = 16;
4733
+ var mintRegistrationToken = async (clientId) => {
4734
+ const plain = generateSecureToken(REG_TOKEN_BYTES);
4735
+ return {
4736
+ plain,
4737
+ record: {
4738
+ clientId,
4739
+ createdAt: Date.now(),
4740
+ tokenHash: await hashToken(plain)
4741
+ }
4742
+ };
4743
+ };
4744
+ var metadataToClient = (clientId, metadata, transform) => {
4745
+ const requestedScopes = metadata.scope === undefined || metadata.scope.length === 0 ? [] : metadata.scope.split(" ").filter((entry) => entry.length > 0);
4746
+ const base = {
4747
+ backchannelLogoutUri: metadata.backchannel_logout_uri,
4748
+ clientId,
4749
+ jwks: metadata.jwks,
4750
+ jwksUri: metadata.jwks_uri,
4751
+ name: metadata.client_name ?? clientId,
4752
+ postLogoutRedirectUris: metadata.post_logout_redirect_uris,
4753
+ redirectUris: metadata.redirect_uris ?? [],
4754
+ scopes: requestedScopes
4755
+ };
4756
+ return { ...base, ...transform, clientId };
4757
+ };
4758
+ var clientToMetadata = (client) => ({
4759
+ backchannel_logout_uri: client.backchannelLogoutUri,
4760
+ client_id: client.clientId,
4761
+ client_name: client.name,
4762
+ jwks: client.jwks,
4763
+ jwks_uri: client.jwksUri,
4764
+ post_logout_redirect_uris: client.postLogoutRedirectUris,
4765
+ redirect_uris: client.redirectUris,
4766
+ scope: client.scopes.join(" ")
4767
+ });
4768
+ var readRegistrationAccessToken = (authorization) => {
4769
+ const prefix = "Bearer ";
4770
+ if (authorization === undefined || !authorization.startsWith(prefix)) {
4771
+ return;
4772
+ }
4773
+ return authorization.slice(prefix.length).trim();
4774
+ };
4775
+ var authorizeManagement = async ({
4776
+ authorization,
4777
+ clientId,
4778
+ registrationTokenStore
4779
+ }) => {
4780
+ const presented = readRegistrationAccessToken(authorization);
4781
+ if (presented === undefined)
4782
+ return false;
4783
+ const record = await registrationTokenStore.findByTokenHash(await hashToken(presented));
4784
+ return record?.clientId === clientId;
4785
+ };
4786
+ var deleteRegisteredClient = async ({
4787
+ authorization,
4788
+ clientId,
4789
+ clientStore,
4790
+ registrationTokenStore
4791
+ }) => {
4792
+ if (clientStore.deleteClient === undefined) {
4793
+ return {
4794
+ body: { error: "unsupported_response_type" },
4795
+ status: 501
4796
+ };
4797
+ }
4798
+ const authed = await authorizeManagement({
4799
+ authorization,
4800
+ clientId,
4801
+ registrationTokenStore
4802
+ });
4803
+ if (!authed)
4804
+ return { body: { error: "invalid_token" }, status: 401 };
4805
+ await clientStore.deleteClient(clientId);
4806
+ await registrationTokenStore.deleteByClientId(clientId);
4807
+ return { status: 204 };
4808
+ };
4809
+ var getRegisteredClient = async ({
4810
+ authorization,
4811
+ clientId,
4812
+ clientStore,
4813
+ registrationTokenStore
4814
+ }) => {
4815
+ const authed = await authorizeManagement({
4816
+ authorization,
4817
+ clientId,
4818
+ registrationTokenStore
4819
+ });
4820
+ if (!authed)
4821
+ return { body: { error: "invalid_token" }, status: 401 };
4822
+ const client = await clientStore.findClient(clientId);
4823
+ if (client === undefined) {
4824
+ return { body: { error: "invalid_client" }, status: 404 };
4825
+ }
4826
+ return { body: clientToMetadata(client), status: 200 };
4827
+ };
4828
+ var registerClient = async ({
4829
+ clientStore,
4830
+ initialAccessTokenStore,
4831
+ metadata,
4832
+ onClientRegistration,
4833
+ presentedInitialAccessToken,
4834
+ registrationBaseUrl,
4835
+ registrationTokenStore
4836
+ }) => {
4837
+ if (clientStore.saveClient === undefined || clientStore.findClient === undefined) {
4838
+ return {
4839
+ body: { error: "unsupported_response_type" },
4840
+ ok: false,
4841
+ status: 501
4842
+ };
4843
+ }
4844
+ if (initialAccessTokenStore !== undefined) {
4845
+ if (presentedInitialAccessToken === undefined) {
4846
+ return { body: { error: "invalid_token" }, ok: false, status: 401 };
4847
+ }
4848
+ const consumed = await initialAccessTokenStore.consumeToken(await hashToken(presentedInitialAccessToken));
4849
+ if (!consumed) {
4850
+ return { body: { error: "invalid_token" }, ok: false, status: 401 };
4851
+ }
4852
+ }
4853
+ if (!Array.isArray(metadata.redirect_uris) || metadata.redirect_uris.length === 0) {
4854
+ return {
4855
+ body: { error: "invalid_redirect_uri" },
4856
+ ok: false,
4857
+ status: 400
4858
+ };
4859
+ }
4860
+ const decision = await onClientRegistration?.({ metadata }) ?? { allow: true };
4861
+ if (!decision.allow) {
4862
+ return {
4863
+ body: {
4864
+ error: "invalid_client_metadata",
4865
+ error_description: decision.denyReason
4866
+ },
4867
+ ok: false,
4868
+ status: 403
4869
+ };
4870
+ }
4871
+ const clientId = generateSecureToken(CLIENT_ID_BYTES);
4872
+ const client = metadataToClient(clientId, metadata, decision.transform);
4873
+ await clientStore.saveClient(client);
4874
+ const regToken = await mintRegistrationToken(clientId);
4875
+ await registrationTokenStore.saveToken(regToken.record);
4876
+ return {
4877
+ body: {
4878
+ ...clientToMetadata(client),
4879
+ registration_access_token: regToken.plain,
4880
+ registration_client_uri: `${registrationBaseUrl}/${clientId}`
4881
+ },
4882
+ ok: true
4883
+ };
4884
+ };
4885
+ var updateRegisteredClient = async ({
4886
+ authorization,
4887
+ clientId,
4888
+ clientStore,
4889
+ metadata,
4890
+ onClientRegistration,
4891
+ registrationTokenStore
4892
+ }) => {
4893
+ if (clientStore.updateClient === undefined) {
4894
+ return {
4895
+ body: { error: "unsupported_response_type" },
4896
+ status: 501
4897
+ };
4898
+ }
4899
+ const authed = await authorizeManagement({
4900
+ authorization,
4901
+ clientId,
4902
+ registrationTokenStore
4903
+ });
4904
+ if (!authed)
4905
+ return { body: { error: "invalid_token" }, status: 401 };
4906
+ const decision = await onClientRegistration?.({ metadata }) ?? { allow: true };
4907
+ if (!decision.allow) {
4908
+ return {
4909
+ body: {
4910
+ error: "invalid_client_metadata",
4911
+ error_description: decision.denyReason
4912
+ },
4913
+ status: 403
4914
+ };
4915
+ }
4916
+ if (!Array.isArray(metadata.redirect_uris) || metadata.redirect_uris.length === 0) {
4917
+ return {
4918
+ body: { error: "invalid_redirect_uri" },
4919
+ status: 400
4920
+ };
4921
+ }
4922
+ const updated = metadataToClient(clientId, metadata, decision.transform);
4923
+ await clientStore.updateClient(clientId, updated);
4924
+ const rotated = await mintRegistrationToken(clientId);
4925
+ await registrationTokenStore.saveToken(rotated.record);
4926
+ return {
4927
+ body: {
4928
+ ...clientToMetadata(updated),
4929
+ registration_access_token: rotated.plain
4930
+ },
4931
+ status: 200
4932
+ };
4933
+ };
4934
+
4631
4935
  // src/oidc/routes.ts
4632
4936
  var HTTP_OK2 = 200;
4937
+ var HTTP_NO_CONTENT = 204;
4938
+ var HTTP_FOUND = 302;
4633
4939
  var HTTP_BAD_REQUEST2 = 400;
4634
4940
  var HTTP_UNAUTHORIZED2 = 401;
4635
- var HTTP_FOUND = 302;
4941
+ var HTTP_NOT_IMPLEMENTED = 501;
4636
4942
  var CODE_TTL_MINUTES = 10;
4637
4943
  var CODE_TTL_MS = MILLISECONDS_IN_A_MINUTE * CODE_TTL_MINUTES;
4638
4944
  var TOKEN_BYTES3 = 32;
@@ -4682,6 +4988,8 @@ var oidcProviderRoutes = (config) => {
4682
4988
  const deviceAuthorizationRoute = `${oidcRoute}/device_authorization`;
4683
4989
  const deviceApproveRoute = `${oidcRoute}/device/decision`;
4684
4990
  const endSessionRoute = `${oidcRoute}/end_session`;
4991
+ const registrationRoute = `${oidcRoute}/register`;
4992
+ const registrationBaseUrl = `${issuer}${registrationRoute}`;
4685
4993
  const tokenUrl = `${issuer}${oidcRoute}/token`;
4686
4994
  const authenticateClient = async (clientId, clientSecret) => {
4687
4995
  const client = await clientStore.findClient(clientId);
@@ -4694,6 +5002,28 @@ var oidcProviderRoutes = (config) => {
4694
5002
  const matches = await constantTimeEqual(await hashToken(clientSecret), client.hashedSecret);
4695
5003
  return matches ? client : undefined;
4696
5004
  };
5005
+ const authenticateTokenClient = async ({
5006
+ basicClientId,
5007
+ basicClientSecret,
5008
+ bodyClientAssertion,
5009
+ bodyClientAssertionType,
5010
+ bodyClientId,
5011
+ bodyClientSecret
5012
+ }) => {
5013
+ if (bodyClientAssertion !== undefined && bodyClientAssertionType === CLIENT_ASSERTION_TYPE) {
5014
+ return verifyClientAssertion({
5015
+ assertion: bodyClientAssertion,
5016
+ expectedAudience: tokenUrl,
5017
+ jtiStore: config.clientAssertionJtiStore,
5018
+ resolveClient: clientStore.findClient
5019
+ });
5020
+ }
5021
+ const clientId = bodyClientId ?? basicClientId;
5022
+ const clientSecret = bodyClientSecret ?? basicClientSecret;
5023
+ if (clientId === undefined)
5024
+ return;
5025
+ return authenticateClient(clientId, clientSecret);
5026
+ };
4697
5027
  const grantAuthorizationCode = async (client, body, dpop) => {
4698
5028
  const {
4699
5029
  code,
@@ -4842,12 +5172,17 @@ var oidcProviderRoutes = (config) => {
4842
5172
  token_endpoint_auth_methods_supported: [
4843
5173
  "client_secret_basic",
4844
5174
  "client_secret_post",
4845
- "none"
4846
- ]
5175
+ "none",
5176
+ "private_key_jwt"
5177
+ ],
5178
+ token_endpoint_auth_signing_alg_values_supported: ["ES256"]
4847
5179
  };
4848
5180
  if (config.deviceAuthorizationStore) {
4849
5181
  discovery.device_authorization_endpoint = `${issuer}${deviceAuthorizationRoute}`;
4850
5182
  }
5183
+ if (config.clientRegistrationTokenStore !== undefined) {
5184
+ discovery.registration_endpoint = registrationBaseUrl;
5185
+ }
4851
5186
  const handleEndSession = async ({
4852
5187
  cookie,
4853
5188
  inMemorySession,
@@ -4968,12 +5303,14 @@ var oidcProviderRoutes = (config) => {
4968
5303
  })
4969
5304
  }).post(tokenRoute, async ({ body, headers }) => {
4970
5305
  const basic = readBasicAuth2(headers.authorization);
4971
- const clientId = basic.clientId ?? body.client_id;
4972
- const clientSecret = basic.clientSecret ?? body.client_secret;
4973
- if (clientId === undefined) {
4974
- return oauthError2(HTTP_UNAUTHORIZED2, "invalid_client");
4975
- }
4976
- const client = await authenticateClient(clientId, clientSecret);
5306
+ const client = await authenticateTokenClient({
5307
+ basicClientId: basic.clientId,
5308
+ basicClientSecret: basic.clientSecret,
5309
+ bodyClientAssertion: body.client_assertion,
5310
+ bodyClientAssertionType: body.client_assertion_type,
5311
+ bodyClientId: body.client_id,
5312
+ bodyClientSecret: body.client_secret
5313
+ });
4977
5314
  if (client === undefined) {
4978
5315
  return oauthError2(HTTP_UNAUTHORIZED2, "invalid_client");
4979
5316
  }
@@ -4993,6 +5330,8 @@ var oidcProviderRoutes = (config) => {
4993
5330
  }, {
4994
5331
  body: t12.Object({
4995
5332
  audience: t12.Optional(t12.String()),
5333
+ client_assertion: t12.Optional(t12.String()),
5334
+ client_assertion_type: t12.Optional(t12.String()),
4996
5335
  client_id: t12.Optional(t12.String()),
4997
5336
  client_secret: t12.Optional(t12.String()),
4998
5337
  code: t12.Optional(t12.String()),
@@ -5157,6 +5496,96 @@ var oidcProviderRoutes = (config) => {
5157
5496
  cookie: t12.Cookie({
5158
5497
  user_session_id: t12.Optional(userSessionIdTypebox)
5159
5498
  })
5499
+ }).post(registrationRoute, async ({ body, headers }) => {
5500
+ if (config.clientRegistrationTokenStore === undefined) {
5501
+ return jsonResponse({ error: "unsupported_response_type" }, HTTP_NOT_IMPLEMENTED);
5502
+ }
5503
+ const presented = headers.authorization?.startsWith("Bearer ") ? headers.authorization.slice("Bearer ".length).trim() : undefined;
5504
+ const result = await registerClient({
5505
+ clientStore,
5506
+ initialAccessTokenStore: config.initialAccessTokenStore,
5507
+ metadata: body,
5508
+ onClientRegistration: config.onClientRegistration,
5509
+ presentedInitialAccessToken: presented,
5510
+ registrationBaseUrl,
5511
+ registrationTokenStore: config.clientRegistrationTokenStore
5512
+ });
5513
+ return jsonResponse(result.body, result.ok ? HTTP_OK2 : result.status);
5514
+ }, {
5515
+ body: t12.Object({
5516
+ backchannel_logout_uri: t12.Optional(t12.String()),
5517
+ client_name: t12.Optional(t12.String()),
5518
+ jwks: t12.Optional(t12.Any()),
5519
+ jwks_uri: t12.Optional(t12.String()),
5520
+ post_logout_redirect_uris: t12.Optional(t12.Array(t12.String())),
5521
+ redirect_uris: t12.Optional(t12.Array(t12.String())),
5522
+ scope: t12.Optional(t12.String())
5523
+ }),
5524
+ headers: t12.Object({
5525
+ authorization: t12.Optional(t12.String())
5526
+ })
5527
+ }).get(`${registrationRoute}/:clientId`, async ({ headers, params: { clientId } }) => {
5528
+ if (config.clientRegistrationTokenStore === undefined) {
5529
+ return jsonResponse({ error: "unsupported_response_type" }, HTTP_NOT_IMPLEMENTED);
5530
+ }
5531
+ const result = await getRegisteredClient({
5532
+ authorization: headers.authorization,
5533
+ clientId,
5534
+ clientStore,
5535
+ registrationTokenStore: config.clientRegistrationTokenStore
5536
+ });
5537
+ return jsonResponse(result.body, result.status);
5538
+ }, {
5539
+ headers: t12.Object({
5540
+ authorization: t12.Optional(t12.String())
5541
+ }),
5542
+ params: t12.Object({ clientId: t12.String() })
5543
+ }).put(`${registrationRoute}/:clientId`, async ({ body, headers, params: { clientId } }) => {
5544
+ if (config.clientRegistrationTokenStore === undefined) {
5545
+ return jsonResponse({ error: "unsupported_response_type" }, HTTP_NOT_IMPLEMENTED);
5546
+ }
5547
+ const result = await updateRegisteredClient({
5548
+ authorization: headers.authorization,
5549
+ clientId,
5550
+ clientStore,
5551
+ metadata: body,
5552
+ onClientRegistration: config.onClientRegistration,
5553
+ registrationTokenStore: config.clientRegistrationTokenStore
5554
+ });
5555
+ return jsonResponse(result.body, result.status);
5556
+ }, {
5557
+ body: t12.Object({
5558
+ backchannel_logout_uri: t12.Optional(t12.String()),
5559
+ client_name: t12.Optional(t12.String()),
5560
+ jwks: t12.Optional(t12.Any()),
5561
+ jwks_uri: t12.Optional(t12.String()),
5562
+ post_logout_redirect_uris: t12.Optional(t12.Array(t12.String())),
5563
+ redirect_uris: t12.Optional(t12.Array(t12.String())),
5564
+ scope: t12.Optional(t12.String())
5565
+ }),
5566
+ headers: t12.Object({
5567
+ authorization: t12.Optional(t12.String())
5568
+ }),
5569
+ params: t12.Object({ clientId: t12.String() })
5570
+ }).delete(`${registrationRoute}/:clientId`, async ({ headers, params: { clientId } }) => {
5571
+ if (config.clientRegistrationTokenStore === undefined) {
5572
+ return jsonResponse({ error: "unsupported_response_type" }, HTTP_NOT_IMPLEMENTED);
5573
+ }
5574
+ const result = await deleteRegisteredClient({
5575
+ authorization: headers.authorization,
5576
+ clientId,
5577
+ clientStore,
5578
+ registrationTokenStore: config.clientRegistrationTokenStore
5579
+ });
5580
+ if (result.status === HTTP_NO_CONTENT) {
5581
+ return new Response(null, { status: HTTP_NO_CONTENT });
5582
+ }
5583
+ return jsonResponse(result.body, result.status);
5584
+ }, {
5585
+ headers: t12.Object({
5586
+ authorization: t12.Optional(t12.String())
5587
+ }),
5588
+ params: t12.Object({ clientId: t12.String() })
5160
5589
  }).get(jwksRoute, () => ({ keys: [toPublicJwk(signingKey)] })).get("/.well-known/openid-configuration", () => discovery);
5161
5590
  };
5162
5591
 
@@ -20310,6 +20739,23 @@ var createInMemoryAuthorizationCodeStore = () => {
20310
20739
  }
20311
20740
  };
20312
20741
  };
20742
+ var createInMemoryClientAssertionJtiStore = () => {
20743
+ const seen = new Map;
20744
+ return {
20745
+ recordIfFresh: async (clientId, jti, expiresAt) => {
20746
+ const now = Date.now();
20747
+ for (const [key, expiry] of seen) {
20748
+ if (expiry < now)
20749
+ seen.delete(key);
20750
+ }
20751
+ const composite = `${clientId}|${jti}`;
20752
+ if (seen.has(composite))
20753
+ return false;
20754
+ seen.set(composite, expiresAt);
20755
+ return true;
20756
+ }
20757
+ };
20758
+ };
20313
20759
  var createInMemoryDeviceAuthorizationStore = () => {
20314
20760
  const byDeviceCode = new Map;
20315
20761
  return {
@@ -20349,10 +20795,49 @@ var createInMemoryLogoutDeliveryStore = () => {
20349
20795
  }
20350
20796
  };
20351
20797
  };
20798
+ var createInMemoryClientRegistrationTokenStore = () => {
20799
+ const byHash = new Map;
20800
+ return {
20801
+ deleteByClientId: async (clientId) => {
20802
+ for (const [hash, token] of byHash) {
20803
+ if (token.clientId === clientId)
20804
+ byHash.delete(hash);
20805
+ }
20806
+ },
20807
+ findByTokenHash: async (tokenHash) => byHash.get(tokenHash),
20808
+ saveToken: async (token) => {
20809
+ for (const [hash, existing] of byHash) {
20810
+ if (existing.clientId === token.clientId)
20811
+ byHash.delete(hash);
20812
+ }
20813
+ byHash.set(token.tokenHash, { ...token });
20814
+ }
20815
+ };
20816
+ };
20817
+ var createInMemoryInitialAccessTokenStore = (initialHashes = []) => {
20818
+ const remaining = new Set(initialHashes);
20819
+ return {
20820
+ consumeToken: async (tokenHash) => {
20821
+ if (!remaining.has(tokenHash))
20822
+ return false;
20823
+ remaining.delete(tokenHash);
20824
+ return true;
20825
+ }
20826
+ };
20827
+ };
20352
20828
  var createInMemoryOAuthClientStore = (clients) => {
20353
20829
  const registry = new Map(clients.map((client) => [client.clientId, client]));
20354
20830
  return {
20355
- findClient: async (clientId) => registry.get(clientId)
20831
+ deleteClient: async (clientId) => {
20832
+ registry.delete(clientId);
20833
+ },
20834
+ findClient: async (clientId) => registry.get(clientId),
20835
+ saveClient: async (client) => {
20836
+ registry.set(client.clientId, { ...client });
20837
+ },
20838
+ updateClient: async (clientId, client) => {
20839
+ registry.set(clientId, { ...client });
20840
+ }
20356
20841
  };
20357
20842
  };
20358
20843
  var createInMemoryOidcRefreshTokenStore = () => {
@@ -20384,12 +20869,27 @@ var createInMemoryOidcRefreshTokenStore = () => {
20384
20869
  var URL_LENGTH = 2048;
20385
20870
  var DEFAULT_LIST_LIMIT2 = 100;
20386
20871
  var ID_LENGTH7 = 255;
20872
+ var oauthClientAssertionJtisTable = pgTable("auth_oauth_client_assertion_jtis", {
20873
+ client_id: varchar("client_id", { length: ID_LENGTH7 }).notNull(),
20874
+ composite_key: varchar("composite_key", {
20875
+ length: ID_LENGTH7
20876
+ }).primaryKey(),
20877
+ expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
20878
+ jti: varchar("jti", { length: ID_LENGTH7 }).notNull()
20879
+ });
20880
+ var oauthClientRegistrationTokensTable = pgTable("auth_oauth_client_registration_tokens", {
20881
+ client_id: varchar("client_id", { length: ID_LENGTH7 }).notNull(),
20882
+ created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
20883
+ token_hash: varchar("token_hash", { length: ID_LENGTH7 }).primaryKey()
20884
+ });
20387
20885
  var oauthClientsTable = pgTable("auth_oauth_clients", {
20388
20886
  backchannel_logout_uri: varchar("backchannel_logout_uri", {
20389
20887
  length: URL_LENGTH
20390
20888
  }),
20391
20889
  client_id: varchar("client_id", { length: ID_LENGTH7 }).primaryKey(),
20392
20890
  hashed_secret: varchar("hashed_secret", { length: ID_LENGTH7 }),
20891
+ jwks_json: jsonb("jwks_json").$type(),
20892
+ jwks_uri: varchar("jwks_uri", { length: URL_LENGTH }),
20393
20893
  name: varchar("name", { length: ID_LENGTH7 }).notNull(),
20394
20894
  post_logout_redirect_uris: text("post_logout_redirect_uris").array(),
20395
20895
  redirect_uris: text("redirect_uris").array().notNull(),
@@ -20421,6 +20921,9 @@ var oauthDeviceAuthorizationsTable = pgTable("auth_oauth_device_authorizations",
20421
20921
  user_code: varchar("user_code", { length: 16 }).notNull().unique(),
20422
20922
  user_sub: varchar("user_sub", { length: ID_LENGTH7 })
20423
20923
  });
20924
+ var oauthInitialAccessTokensTable = pgTable("auth_oauth_initial_access_tokens", {
20925
+ token_hash: varchar("token_hash", { length: ID_LENGTH7 }).primaryKey()
20926
+ });
20424
20927
  var oauthLogoutDeliveriesTable = pgTable("auth_oauth_logout_deliveries", {
20425
20928
  attempts: bigint("attempts", { mode: "number" }).notNull(),
20426
20929
  client_id: varchar("client_id", { length: ID_LENGTH7 }).notNull(),
@@ -20446,6 +20949,8 @@ var toClient2 = (row) => ({
20446
20949
  backchannelLogoutUri: row.backchannel_logout_uri ?? undefined,
20447
20950
  clientId: row.client_id,
20448
20951
  hashedSecret: row.hashed_secret ?? undefined,
20952
+ jwks: row.jwks_json ?? undefined,
20953
+ jwksUri: row.jwks_uri ?? undefined,
20449
20954
  name: row.name,
20450
20955
  postLogoutRedirectUris: row.post_logout_redirect_uris ?? undefined,
20451
20956
  redirectUris: row.redirect_uris,
@@ -20520,7 +21025,10 @@ var toRefreshValues = (token) => ({
20520
21025
  user_id: token.userId
20521
21026
  });
20522
21027
  var createNeonAuthorizationCodeStore = (databaseUrl) => createPostgresAuthorizationCodeStore(createNeonDatabase(databaseUrl));
21028
+ var createNeonClientAssertionJtiStore = (databaseUrl) => createPostgresClientAssertionJtiStore(createNeonDatabase(databaseUrl));
21029
+ var createNeonClientRegistrationTokenStore = (databaseUrl) => createPostgresClientRegistrationTokenStore(createNeonDatabase(databaseUrl));
20523
21030
  var createNeonDeviceAuthorizationStore = (databaseUrl) => createPostgresDeviceAuthorizationStore(createNeonDatabase(databaseUrl));
21031
+ var createNeonInitialAccessTokenStore = (databaseUrl) => createPostgresInitialAccessTokenStore(createNeonDatabase(databaseUrl));
20524
21032
  var createNeonLogoutDeliveryStore = (databaseUrl) => createPostgresLogoutDeliveryStore(createNeonDatabase(databaseUrl));
20525
21033
  var createNeonOAuthClientStore = (databaseUrl) => createPostgresOAuthClientStore(createNeonDatabase(databaseUrl));
20526
21034
  var createNeonOidcRefreshTokenStore = (databaseUrl) => createPostgresOidcRefreshTokenStore(createNeonDatabase(databaseUrl));
@@ -20533,6 +21041,47 @@ var createPostgresAuthorizationCodeStore = (db) => ({
20533
21041
  await db.insert(oauthCodesTable).values(toCodeValues(code));
20534
21042
  }
20535
21043
  });
21044
+ var createPostgresClientAssertionJtiStore = (db) => ({
21045
+ recordIfFresh: async (clientId, jti, expiresAt) => {
21046
+ await db.delete(oauthClientAssertionJtisTable).where(lt(oauthClientAssertionJtisTable.expires_at_ms, Date.now()));
21047
+ const compositeKey = `${clientId}|${jti}`;
21048
+ try {
21049
+ await db.insert(oauthClientAssertionJtisTable).values({
21050
+ client_id: clientId,
21051
+ composite_key: compositeKey,
21052
+ expires_at_ms: expiresAt,
21053
+ jti
21054
+ });
21055
+ return true;
21056
+ } catch {
21057
+ return false;
21058
+ }
21059
+ }
21060
+ });
21061
+ var createPostgresClientRegistrationTokenStore = (db) => ({
21062
+ deleteByClientId: async (clientId) => {
21063
+ await db.delete(oauthClientRegistrationTokensTable).where(eq(oauthClientRegistrationTokensTable.client_id, clientId));
21064
+ },
21065
+ findByTokenHash: async (tokenHash) => {
21066
+ const [row] = await db.select().from(oauthClientRegistrationTokensTable).where(eq(oauthClientRegistrationTokensTable.token_hash, tokenHash)).limit(1);
21067
+ if (!row)
21068
+ return;
21069
+ const token = {
21070
+ clientId: row.client_id,
21071
+ createdAt: row.created_at_ms,
21072
+ tokenHash: row.token_hash
21073
+ };
21074
+ return token;
21075
+ },
21076
+ saveToken: async (token) => {
21077
+ await db.delete(oauthClientRegistrationTokensTable).where(eq(oauthClientRegistrationTokensTable.client_id, token.clientId));
21078
+ await db.insert(oauthClientRegistrationTokensTable).values({
21079
+ client_id: token.clientId,
21080
+ created_at_ms: token.createdAt,
21081
+ token_hash: token.tokenHash
21082
+ });
21083
+ }
21084
+ });
20536
21085
  var createPostgresDeviceAuthorizationStore = (db) => ({
20537
21086
  deleteByDeviceCodeHash: async (deviceCodeHash) => {
20538
21087
  await db.delete(oauthDeviceAuthorizationsTable).where(eq(oauthDeviceAuthorizationsTable.device_code_hash, deviceCodeHash));
@@ -20562,6 +21111,12 @@ var createPostgresDeviceAuthorizationStore = (db) => ({
20562
21111
  await db.update(oauthDeviceAuthorizationsTable).set({ status, user_sub: userSub ?? null }).where(eq(oauthDeviceAuthorizationsTable.device_code_hash, deviceCodeHash));
20563
21112
  }
20564
21113
  });
21114
+ var createPostgresInitialAccessTokenStore = (db) => ({
21115
+ consumeToken: async (tokenHash) => {
21116
+ const deleted = await db.delete(oauthInitialAccessTokensTable).where(eq(oauthInitialAccessTokensTable.token_hash, tokenHash)).returning({ token_hash: oauthInitialAccessTokensTable.token_hash });
21117
+ return deleted.length > 0;
21118
+ }
21119
+ });
20565
21120
  var createPostgresLogoutDeliveryStore = (db) => ({
20566
21121
  listFailed: async (limit = DEFAULT_LIST_LIMIT2) => {
20567
21122
  const rows = await db.select().from(oauthLogoutDeliveriesTable).orderBy(desc(oauthLogoutDeliveriesTable.created_at_ms)).limit(limit);
@@ -20584,10 +21139,30 @@ var createPostgresLogoutDeliveryStore = (db) => ({
20584
21139
  await db.delete(oauthLogoutDeliveriesTable).where(eq(oauthLogoutDeliveriesTable.id, deliveryId));
20585
21140
  }
20586
21141
  });
21142
+ var toClientValues2 = (client) => ({
21143
+ backchannel_logout_uri: client.backchannelLogoutUri ?? null,
21144
+ client_id: client.clientId,
21145
+ hashed_secret: client.hashedSecret ?? null,
21146
+ jwks_json: client.jwks ?? null,
21147
+ jwks_uri: client.jwksUri ?? null,
21148
+ name: client.name,
21149
+ post_logout_redirect_uris: client.postLogoutRedirectUris ?? null,
21150
+ redirect_uris: client.redirectUris,
21151
+ scopes: client.scopes
21152
+ });
20587
21153
  var createPostgresOAuthClientStore = (db) => ({
21154
+ deleteClient: async (clientId) => {
21155
+ await db.delete(oauthClientsTable).where(eq(oauthClientsTable.client_id, clientId));
21156
+ },
20588
21157
  findClient: async (clientId) => {
20589
21158
  const [row] = await db.select().from(oauthClientsTable).where(eq(oauthClientsTable.client_id, clientId)).limit(1);
20590
21159
  return row ? toClient2(row) : undefined;
21160
+ },
21161
+ saveClient: async (client) => {
21162
+ await db.insert(oauthClientsTable).values(toClientValues2(client));
21163
+ },
21164
+ updateClient: async (clientId, client) => {
21165
+ await db.update(oauthClientsTable).set(toClientValues2(client)).where(eq(oauthClientsTable.client_id, clientId));
20591
21166
  }
20592
21167
  });
20593
21168
  var createPostgresOidcRefreshTokenStore = (db) => ({
@@ -22033,6 +22608,7 @@ export {
22033
22608
  verifyIdTokenHint,
22034
22609
  verifyHcaptcha,
22035
22610
  verifyDpopProof,
22611
+ verifyClientAssertion,
22036
22612
  verifyAuditChain,
22037
22613
  verifyApiKey,
22038
22614
  verifyAccessToken,
@@ -22040,6 +22616,7 @@ export {
22040
22616
  validateSession,
22041
22617
  validateEmailDeliverability,
22042
22618
  userSessionIdTypebox,
22619
+ updateRegisteredClient,
22043
22620
  trustDevice,
22044
22621
  toPublicJwk,
22045
22622
  switchActiveSession,
@@ -22077,6 +22654,7 @@ export {
22077
22654
  resolveAuthHtmxRenderers,
22078
22655
  resolveApiPrincipal,
22079
22656
  removeFromSessionRing,
22657
+ registerClient,
22080
22658
  refreshableProviderOptions,
22081
22659
  recordLoginAttempt,
22082
22660
  readSessionRing,
@@ -22098,9 +22676,12 @@ export {
22098
22676
  oidcProviderOptions,
22099
22677
  oauthRefreshTokensTable,
22100
22678
  oauthLogoutDeliveriesTable,
22679
+ oauthInitialAccessTokensTable,
22101
22680
  oauthDeviceAuthorizationsTable,
22102
22681
  oauthCodesTable,
22103
22682
  oauthClientsTable,
22683
+ oauthClientRegistrationTokensTable,
22684
+ oauthClientAssertionJtisTable,
22104
22685
  mintLogoutToken,
22105
22686
  mfaTotpRoutes,
22106
22687
  mfaRoutes,
@@ -22143,6 +22724,7 @@ export {
22143
22724
  hasOrganizationScope,
22144
22725
  getUserSessionId,
22145
22726
  getStatus,
22727
+ getRegisteredClient,
22146
22728
  generateTotpSecret,
22147
22729
  generateTotp,
22148
22730
  generateSigningKey,
@@ -22162,6 +22744,7 @@ export {
22162
22744
  encryptSecret,
22163
22745
  denyDeviceAuthorization,
22164
22746
  deleteWarrant,
22747
+ deleteRegisteredClient,
22165
22748
  defineProvidersConfiguration,
22166
22749
  defineAuthSettings,
22167
22750
  defineAuthHtmxConfig,
@@ -22206,8 +22789,11 @@ export {
22206
22789
  createPostgresLoginHistoryStore,
22207
22790
  createPostgresLockoutStore,
22208
22791
  createPostgresKnownDeviceStore,
22792
+ createPostgresInitialAccessTokenStore,
22209
22793
  createPostgresDeviceAuthorizationStore,
22210
22794
  createPostgresCredentialStore,
22795
+ createPostgresClientRegistrationTokenStore,
22796
+ createPostgresClientAssertionJtiStore,
22211
22797
  createPostgresAuthorizationCodeStore,
22212
22798
  createPostgresAuditSink,
22213
22799
  createPostgresApiKeyStore,
@@ -22234,9 +22820,12 @@ export {
22234
22820
  createNeonLockoutStore,
22235
22821
  createNeonLinkedProviderStores,
22236
22822
  createNeonKnownDeviceStore,
22823
+ createNeonInitialAccessTokenStore,
22237
22824
  createNeonDeviceAuthorizationStore,
22238
22825
  createNeonDatabase,
22239
22826
  createNeonCredentialStore,
22827
+ createNeonClientRegistrationTokenStore,
22828
+ createNeonClientAssertionJtiStore,
22240
22829
  createNeonAuthorizationCodeStore,
22241
22830
  createNeonAuthSessionStore,
22242
22831
  createNeonAuditSink,
@@ -22265,8 +22854,11 @@ export {
22265
22854
  createInMemoryLockoutStore,
22266
22855
  createInMemoryLinkedProviderStores,
22267
22856
  createInMemoryKnownDeviceStore,
22857
+ createInMemoryInitialAccessTokenStore,
22268
22858
  createInMemoryDeviceAuthorizationStore,
22269
22859
  createInMemoryCredentialStore,
22860
+ createInMemoryClientRegistrationTokenStore,
22861
+ createInMemoryClientAssertionJtiStore,
22270
22862
  createInMemoryCheckCache,
22271
22863
  createInMemoryAuthorizationCodeStore,
22272
22864
  createInMemoryAuthSessionStore,
@@ -22332,8 +22924,9 @@ export {
22332
22924
  DEFAULT_INVITATION_TTL_MS,
22333
22925
  DEFAULT_CREDENTIAL_SESSION_TTL_MS,
22334
22926
  DEFAULT_BACKUP_CODE_COUNT,
22927
+ CLIENT_ASSERTION_TYPE,
22335
22928
  AuthIdentityConflictError
22336
22929
  };
22337
22930
 
22338
- //# debugId=9518CC46948D590564756E2164756E21
22931
+ //# debugId=670CF7C3F8CEA35064756E2164756E21
22339
22932
  //# sourceMappingURL=index.js.map