@absolutejs/auth 0.27.0-beta.4 → 0.27.0-beta.5

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
@@ -13477,6 +13477,8 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
13477
13477
  [x: string]: {
13478
13478
  post: {
13479
13479
  body: {
13480
+ audience?: string | undefined;
13481
+ resource?: string | undefined;
13480
13482
  client_id?: string | undefined;
13481
13483
  scope?: string | undefined;
13482
13484
  refresh_token?: string | undefined;
@@ -13485,6 +13487,8 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
13485
13487
  code?: string | undefined;
13486
13488
  redirect_uri?: string | undefined;
13487
13489
  code_verifier?: string | undefined;
13490
+ subject_token?: string | undefined;
13491
+ subject_token_type?: string | undefined;
13488
13492
  };
13489
13493
  params: {};
13490
13494
  query: unknown;
package/dist/index.js CHANGED
@@ -4134,6 +4134,72 @@ var DEFAULT_ACCESS_TOKEN_TTL_MS2 = MILLISECONDS_IN_AN_HOUR;
4134
4134
  var DEFAULT_ID_TOKEN_TTL_MS = MILLISECONDS_IN_AN_HOUR;
4135
4135
  var DEFAULT_REFRESH_TOKEN_TTL_MS = MILLISECONDS_IN_A_DAY * REFRESH_TTL_DAYS;
4136
4136
  var nowSeconds = (milliseconds) => Math.floor(milliseconds / MS_PER_SECOND);
4137
+ var narrowScopes = (available, requested) => requested === undefined || requested.length === 0 ? available : requested.filter((scope) => available.includes(scope));
4138
+ var buildAccessClaims = ({
4139
+ act,
4140
+ audience,
4141
+ clientId,
4142
+ dpopJkt,
4143
+ issuer,
4144
+ now,
4145
+ scopes,
4146
+ sub,
4147
+ ttl
4148
+ }) => {
4149
+ const claims = {
4150
+ aud: audience ?? clientId,
4151
+ client_id: clientId,
4152
+ exp: nowSeconds(now + ttl),
4153
+ iat: nowSeconds(now),
4154
+ iss: issuer,
4155
+ jti: crypto.randomUUID(),
4156
+ scope: scopes.join(" "),
4157
+ sub,
4158
+ token_use: "access"
4159
+ };
4160
+ if (act !== undefined)
4161
+ claims.act = act;
4162
+ if (dpopJkt !== undefined)
4163
+ claims.cnf = { jkt: dpopJkt };
4164
+ return claims;
4165
+ };
4166
+ var exchangeToken = async ({
4167
+ actorClientId,
4168
+ audience,
4169
+ config,
4170
+ dpopJkt,
4171
+ now = Date.now(),
4172
+ requestedScopes,
4173
+ subjectToken
4174
+ }) => {
4175
+ const verified = await verifyJwt(subjectToken, config.signingKey.publicJwk);
4176
+ const payload = verified?.payload;
4177
+ if (payload === undefined || typeof payload.sub !== "string" || typeof payload.exp !== "number" || payload.exp <= nowSeconds(now)) {
4178
+ return { error: "invalid_grant", ok: false };
4179
+ }
4180
+ const available = typeof payload.scope === "string" ? payload.scope.split(" ") : [];
4181
+ if (requestedScopes?.some((scope) => !available.includes(scope)) === true) {
4182
+ return { error: "invalid_scope", ok: false };
4183
+ }
4184
+ const scopes = narrowScopes(available, requestedScopes);
4185
+ const ttl = config.accessTokenTtlMs ?? DEFAULT_ACCESS_TOKEN_TTL_MS2;
4186
+ return {
4187
+ accessToken: await signJwt(buildAccessClaims({
4188
+ act: { sub: actorClientId },
4189
+ audience,
4190
+ clientId: actorClientId,
4191
+ dpopJkt,
4192
+ issuer: config.issuer,
4193
+ now,
4194
+ scopes,
4195
+ sub: payload.sub,
4196
+ ttl
4197
+ }), config.signingKey),
4198
+ expiresIn: Math.floor(ttl / MS_PER_SECOND),
4199
+ ok: true,
4200
+ scope: scopes.join(" ")
4201
+ };
4202
+ };
4137
4203
  var issueTokenSet = async ({
4138
4204
  claims,
4139
4205
  clientId,
@@ -4147,19 +4213,15 @@ var issueTokenSet = async ({
4147
4213
  const accessTtl = config.accessTokenTtlMs ?? DEFAULT_ACCESS_TOKEN_TTL_MS2;
4148
4214
  const idTtl = config.idTokenTtlMs ?? DEFAULT_ID_TOKEN_TTL_MS;
4149
4215
  const refreshTtl = config.refreshTokenTtlMs ?? DEFAULT_REFRESH_TOKEN_TTL_MS;
4150
- const accessPayload = {
4151
- aud: clientId,
4152
- client_id: clientId,
4153
- exp: nowSeconds(now + accessTtl),
4154
- iat: nowSeconds(now),
4155
- iss: config.issuer,
4156
- jti: crypto.randomUUID(),
4157
- scope: scopes.join(" "),
4216
+ const accessPayload = buildAccessClaims({
4217
+ clientId,
4218
+ dpopJkt,
4219
+ issuer: config.issuer,
4220
+ now,
4221
+ scopes,
4158
4222
  sub,
4159
- token_use: "access"
4160
- };
4161
- if (dpopJkt !== undefined)
4162
- accessPayload.cnf = { jkt: dpopJkt };
4223
+ ttl: accessTtl
4224
+ });
4163
4225
  const idPayload = {
4164
4226
  ...claims,
4165
4227
  aud: clientId,
@@ -4190,6 +4252,15 @@ var issueTokenSet = async ({
4190
4252
  token_type: dpopJkt === undefined ? "Bearer" : "DPoP"
4191
4253
  };
4192
4254
  };
4255
+ var mcpProtectedResourceMetadata = ({
4256
+ issuer,
4257
+ resource,
4258
+ scopes
4259
+ }) => ({
4260
+ authorization_servers: [issuer],
4261
+ resource,
4262
+ scopes_supported: scopes ?? []
4263
+ });
4193
4264
  var verifyPkce = async (codeVerifier, codeChallenge) => await hashToken(codeVerifier) === codeChallenge;
4194
4265
 
4195
4266
  // src/oidc/dpop.ts
@@ -4356,11 +4427,45 @@ var oidcProviderRoutes = (config) => {
4356
4427
  sub: record.userId
4357
4428
  }));
4358
4429
  };
4430
+ const grantTokenExchange = async (client, body, dpop) => {
4431
+ if (body.subject_token === undefined) {
4432
+ return oauthError2(HTTP_BAD_REQUEST2, "invalid_request");
4433
+ }
4434
+ const dpopResult = dpop === undefined ? undefined : await verifyDpopProof({
4435
+ htm: "POST",
4436
+ htu: tokenUrl,
4437
+ proof: dpop
4438
+ });
4439
+ if (dpop !== undefined && dpopResult === undefined) {
4440
+ return oauthError2(HTTP_BAD_REQUEST2, "invalid_dpop_proof");
4441
+ }
4442
+ const result = await exchangeToken({
4443
+ actorClientId: client.clientId,
4444
+ audience: body.resource ?? body.audience,
4445
+ config,
4446
+ dpopJkt: dpopResult?.jkt,
4447
+ requestedScopes: body.scope === undefined || body.scope.length === 0 ? undefined : body.scope.split(" "),
4448
+ subjectToken: body.subject_token
4449
+ });
4450
+ if (!result.ok)
4451
+ return oauthError2(HTTP_BAD_REQUEST2, result.error);
4452
+ return jsonResponse({
4453
+ access_token: result.accessToken,
4454
+ expires_in: result.expiresIn,
4455
+ issued_token_type: "urn:ietf:params:oauth:token-type:access_token",
4456
+ scope: result.scope,
4457
+ token_type: dpopResult === undefined ? "Bearer" : "DPoP"
4458
+ }, HTTP_OK2);
4459
+ };
4359
4460
  const discovery = {
4360
4461
  authorization_endpoint: `${issuer}${authorizeRoute}`,
4361
4462
  code_challenge_methods_supported: ["S256"],
4362
4463
  dpop_signing_alg_values_supported: ["ES256"],
4363
- grant_types_supported: ["authorization_code", "refresh_token"],
4464
+ grant_types_supported: [
4465
+ "authorization_code",
4466
+ "refresh_token",
4467
+ "urn:ietf:params:oauth:grant-type:token-exchange"
4468
+ ],
4364
4469
  id_token_signing_alg_values_supported: ["ES256"],
4365
4470
  issuer,
4366
4471
  jwks_uri: `${issuer}${jwksRoute}`,
@@ -4467,9 +4572,13 @@ var oidcProviderRoutes = (config) => {
4467
4572
  if (body.grant_type === "refresh_token") {
4468
4573
  return grantRefreshToken(client, body, headers.dpop);
4469
4574
  }
4575
+ if (body.grant_type === "urn:ietf:params:oauth:grant-type:token-exchange") {
4576
+ return grantTokenExchange(client, body, headers.dpop);
4577
+ }
4470
4578
  return oauthError2(HTTP_BAD_REQUEST2, "unsupported_grant_type");
4471
4579
  }, {
4472
4580
  body: t12.Object({
4581
+ audience: t12.Optional(t12.String()),
4473
4582
  client_id: t12.Optional(t12.String()),
4474
4583
  client_secret: t12.Optional(t12.String()),
4475
4584
  code: t12.Optional(t12.String()),
@@ -4477,7 +4586,10 @@ var oidcProviderRoutes = (config) => {
4477
4586
  grant_type: t12.Optional(t12.String()),
4478
4587
  redirect_uri: t12.Optional(t12.String()),
4479
4588
  refresh_token: t12.Optional(t12.String()),
4480
- scope: t12.Optional(t12.String())
4589
+ resource: t12.Optional(t12.String()),
4590
+ scope: t12.Optional(t12.String()),
4591
+ subject_token: t12.Optional(t12.String()),
4592
+ subject_token_type: t12.Optional(t12.String())
4481
4593
  })
4482
4594
  }).get(jwksRoute, () => ({ keys: [toPublicJwk(signingKey)] })).get("/.well-known/openid-configuration", () => discovery);
4483
4595
  };
@@ -20524,6 +20636,7 @@ export {
20524
20636
  mfaRoutes,
20525
20637
  mfaEnrollmentsTable,
20526
20638
  mfaChallenge,
20639
+ mcpProtectedResourceMetadata,
20527
20640
  loginHistoryTable,
20528
20641
  lockoutsTable,
20529
20642
  listUserSessions,
@@ -20560,6 +20673,7 @@ export {
20560
20673
  generateEncryptionKey,
20561
20674
  generateBackupCodes,
20562
20675
  extractPropFromIdentity,
20676
+ exchangeToken,
20563
20677
  exchangeClientCredentials,
20564
20678
  evaluatePassword,
20565
20679
  endImpersonation,
@@ -20720,5 +20834,5 @@ export {
20720
20834
  AuthIdentityConflictError
20721
20835
  };
20722
20836
 
20723
- //# debugId=C4383EA08F57C5E064756E2164756E21
20837
+ //# debugId=514E4AE78CF406D164756E2164756E21
20724
20838
  //# sourceMappingURL=index.js.map