@absolutejs/auth 0.75.0 → 0.75.2

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/server.js CHANGED
@@ -4256,6 +4256,7 @@ var DEFAULT_AGENT_RESOURCE_METADATA_ROUTE = "/.well-known/oauth-protected-resour
4256
4256
  var agentProtectedResourceMetadata = (config) => ({
4257
4257
  authorization_servers: [config.authorizationServer],
4258
4258
  bearer_methods_supported: ["header"],
4259
+ ...config.dpopBoundAccessTokensRequired === true ? { dpop_bound_access_tokens_required: true } : {},
4259
4260
  ...config.logoUri === undefined ? {} : { resource_logo_uri: config.logoUri },
4260
4261
  ...config.resourceName === undefined ? {} : { resource_name: config.resourceName },
4261
4262
  resource: config.resource,
@@ -7187,8 +7188,8 @@ var createMfaGate = ({ getUserId, mfaStore }) => async (user) => isMfaEnrolled(a
7187
7188
 
7188
7189
  // src/nativePush.ts
7189
7190
  import { Elysia as Elysia17, t as t11 } from "elysia";
7190
- var DEFAULT_PUSH_ROUTE = "/auth/push";
7191
7191
  var DEFAULT_NATIVE_PUSH_ROUTE = "/auth/mobile/push";
7192
+ var DEFAULT_PUSH_ROUTE = "/auth/push";
7192
7193
  var requireServerText = (value, field) => {
7193
7194
  const normalized = value.trim();
7194
7195
  if (!normalized)
@@ -7242,9 +7243,11 @@ var pushRoutes = ({
7242
7243
  }
7243
7244
  return true;
7244
7245
  };
7246
+ const installationIdSchema = t11.Optional(t11.String({ maxLength: 128, minLength: 1 }));
7247
+ const localeSchema = t11.Optional(t11.String({ maxLength: 64, minLength: 1 }));
7245
7248
  const commonRegistrationFields = {
7246
- installationId: t11.Optional(t11.String({ maxLength: 128, minLength: 1 })),
7247
- locale: t11.Optional(t11.String({ maxLength: 64, minLength: 1 }))
7249
+ installationId: installationIdSchema,
7250
+ locale: localeSchema
7248
7251
  };
7249
7252
  const registrationBody = t11.Union([
7250
7253
  t11.Object({
@@ -7264,18 +7267,20 @@ var pushRoutes = ({
7264
7267
  })
7265
7268
  })
7266
7269
  ]);
7270
+ const requirePushPrincipal = ({
7271
+ pushPrincipal,
7272
+ status
7273
+ }) => pushPrincipal ? undefined : status("Unauthorized", "User is not authenticated");
7267
7274
  const registrationOptions = {
7268
- body: registrationBody,
7269
- beforeHandle: ({
7270
- pushPrincipal,
7271
- status
7272
- }) => pushPrincipal ? undefined : status("Unauthorized", "User is not authenticated")
7275
+ beforeHandle: requirePushPrincipal,
7276
+ body: registrationBody
7273
7277
  };
7278
+ const removalBody = t11.Object({
7279
+ installationId: t11.String({ maxLength: 128, minLength: 1 })
7280
+ });
7274
7281
  const removalOptions = {
7275
- body: t11.Object({
7276
- installationId: t11.String({ maxLength: 128, minLength: 1 })
7277
- }),
7278
- beforeHandle: registrationOptions.beforeHandle
7282
+ beforeHandle: requirePushPrincipal,
7283
+ body: removalBody
7279
7284
  };
7280
7285
  return new Elysia17({ name: "@absolutejs/auth/push" }).use(sessionStore()).guard({
7281
7286
  cookie: t11.Cookie({ user_session_id: userSessionIdTypebox }),
@@ -9082,6 +9087,7 @@ var verifyCertificateBoundToken = async ({
9082
9087
  // src/oidc/dpop.ts
9083
9088
  init_constants();
9084
9089
  var DEFAULT_MAX_AGE_MS = 60000;
9090
+ var MAX_JTI_LENGTH = 128;
9085
9091
  var SECONDS_TO_MS = 1000;
9086
9092
  var NONCE_WINDOW_SECONDS = 120;
9087
9093
  var NONCE_WINDOW_MS = NONCE_WINDOW_SECONDS * MILLISECONDS_IN_A_SECOND;
@@ -9122,17 +9128,38 @@ var verifyDpopNonce = async ({
9122
9128
  const candidates = await Promise.all(Array.from({ length: NONCE_PREVIOUS_WINDOWS_ACCEPTED + 1 }, (_, offset) => hmacSha2562(secret, String(currentWindow - offset))));
9123
9129
  return candidates.some((expected) => expected === nonce);
9124
9130
  };
9125
- var decodeHeader = (segment) => JSON.parse(Buffer.from(segment, "base64url").toString("utf8"));
9126
- var normalizeHtu = (value) => {
9131
+ var decodeHeader = (segment) => {
9132
+ try {
9133
+ const value = JSON.parse(Buffer.from(segment, "base64url").toString("utf8"));
9134
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
9135
+ } catch {
9136
+ return;
9137
+ }
9138
+ };
9139
+ var normalizeHtu = (value, proofClaim = false) => {
9127
9140
  try {
9128
9141
  const url = new URL(String(value));
9142
+ if (url.username || url.password || proofClaim && (url.search.length > 0 || url.hash.length > 0))
9143
+ return;
9129
9144
  return `${url.origin}${url.pathname}`;
9130
9145
  } catch {
9131
- return "";
9146
+ return;
9132
9147
  }
9133
9148
  };
9149
+ var isPublicEs256Jwk = (value) => {
9150
+ if (typeof value !== "object" || value === null || Array.isArray(value))
9151
+ return false;
9152
+ const kty = Reflect.get(value, "kty");
9153
+ const crv = Reflect.get(value, "crv");
9154
+ const xCoordinate = Reflect.get(value, "x");
9155
+ const yCoordinate = Reflect.get(value, "y");
9156
+ const privateComponent = Reflect.get(value, "d");
9157
+ const alg = Reflect.get(value, "alg");
9158
+ return kty === "EC" && crv === "P-256" && typeof xCoordinate === "string" && xCoordinate.length > 0 && typeof yCoordinate === "string" && yCoordinate.length > 0 && privateComponent === undefined && (alg === undefined || alg === "ES256");
9159
+ };
9134
9160
  var verifyDpopProof = async ({
9135
9161
  accessToken,
9162
+ consumeJti,
9136
9163
  htm,
9137
9164
  htu,
9138
9165
  isUsedJti,
@@ -9142,14 +9169,20 @@ var verifyDpopProof = async ({
9142
9169
  }) => {
9143
9170
  if (proof === undefined)
9144
9171
  return;
9145
- const [headerSegment] = proof.split(".");
9172
+ const segments = proof.split(".");
9173
+ if (segments.length !== 3)
9174
+ return;
9175
+ const [headerSegment] = segments;
9146
9176
  if (headerSegment === undefined)
9147
9177
  return;
9148
9178
  const header = decodeHeader(headerSegment);
9149
- if (header?.typ !== "dpop+jwt" || header.alg !== "ES256" || header.jwk === undefined) {
9179
+ const publicJwk = header === undefined ? undefined : Reflect.get(header, "jwk");
9180
+ if (header === undefined || Reflect.get(header, "typ") !== "dpop+jwt" || Reflect.get(header, "alg") !== "ES256" || !isPublicEs256Jwk(publicJwk)) {
9150
9181
  return;
9151
9182
  }
9152
- const verified = await verifyJwt(proof, header.jwk);
9183
+ const verified = await verifyJwt(proof, publicJwk).catch(() => {
9184
+ return;
9185
+ });
9153
9186
  if (verified === undefined)
9154
9187
  return;
9155
9188
  const { payload } = verified;
@@ -9159,14 +9192,19 @@ var verifyDpopProof = async ({
9159
9192
  return;
9160
9193
  }
9161
9194
  const iatMs = typeof payload.iat === "number" ? payload.iat * SECONDS_TO_MS : 0;
9162
- if (payload.htm !== htm || normalizeHtu(payload.htu) !== normalizeHtu(htu) || iatMs === 0 || Math.abs(now - iatMs) > maxAgeMs) {
9195
+ const claimedHtu = normalizeHtu(payload.htu, true);
9196
+ const expectedHtu = normalizeHtu(htu);
9197
+ const jti = typeof payload.jti === "string" ? payload.jti : undefined;
9198
+ if (payload.htm !== htm || claimedHtu === undefined || expectedHtu === undefined || claimedHtu !== expectedHtu || iatMs === 0 || Math.abs(now - iatMs) > maxAgeMs || jti === undefined || jti.length === 0 || jti.length > MAX_JTI_LENGTH) {
9163
9199
  return;
9164
9200
  }
9165
- const jti = typeof payload.jti === "string" ? payload.jti : undefined;
9166
- if (jti !== undefined && isUsedJti !== undefined && await isUsedJti(jti)) {
9201
+ const jkt = await jwkThumbprint(publicJwk);
9202
+ if (isUsedJti !== undefined && await isUsedJti(jti)) {
9167
9203
  return;
9168
9204
  }
9169
- return { jkt: await jwkThumbprint(header.jwk), jti };
9205
+ if (consumeJti !== undefined && !await consumeJti({ expiresAt: iatMs + maxAgeMs, jkt, jti }))
9206
+ return;
9207
+ return { jkt, jti };
9170
9208
  };
9171
9209
 
9172
9210
  // src/oidc/logout.ts
@@ -9905,7 +9943,7 @@ var oidcProviderRoutes = (config) => {
9905
9943
  "dpop-nonce": fresh,
9906
9944
  "www-authenticate": 'DPoP error="use_dpop_nonce"'
9907
9945
  },
9908
- status: HTTP_UNAUTHORIZED4
9946
+ status: HTTP_BAD_REQUEST3
9909
9947
  });
9910
9948
  };
9911
9949
  const grantAuthorizationCode = async (client, body, dpop, clientCertThumbprint) => {
@@ -37602,6 +37640,7 @@ var readAudience = (audience) => {
37602
37640
  };
37603
37641
  var createOidcAgentCredentialVerifier = ({
37604
37642
  issuer,
37643
+ consumeDpopJti,
37605
37644
  isUsedDpopJti,
37606
37645
  maxDpopAgeMs,
37607
37646
  publicJwk,
@@ -37630,6 +37669,7 @@ var createOidcAgentCredentialVerifier = ({
37630
37669
  return;
37631
37670
  const proof = await verifyDpopProof({
37632
37671
  accessToken: token,
37672
+ consumeJti: consumeDpopJti,
37633
37673
  htm: request.method,
37634
37674
  htu: request.url,
37635
37675
  isUsedJti: isUsedDpopJti,
@@ -41619,5 +41659,5 @@ export {
41619
41659
  VerificationProviderError
41620
41660
  };
41621
41661
 
41622
- //# debugId=471E09DA92BB95D564756E2164756E21
41662
+ //# debugId=4C7D47096A194ABC64756E2164756E21
41623
41663
  //# sourceMappingURL=server.js.map