@leanmcp/auth 0.4.2 → 0.4.4-alpha.10.96d2437

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.
@@ -148,11 +148,11 @@ var DynamicClientRegistration = class {
148
148
  };
149
149
  }
150
150
  /**
151
- * Register a new OAuth client (stateless)
152
- *
153
- * @param request - Client registration request per RFC 7591
154
- * @returns Client registration response with JWT credentials
155
- */
151
+ * Register a new OAuth client (stateless)
152
+ *
153
+ * @param request - Client registration request per RFC 7591
154
+ * @returns Client registration response with JWT credentials
155
+ */
156
156
  register(request) {
157
157
  const now = Date.now();
158
158
  const nowSeconds = Math.floor(now / 1e3);
@@ -194,12 +194,12 @@ var DynamicClientRegistration = class {
194
194
  return response;
195
195
  }
196
196
  /**
197
- * Validate client credentials (stateless)
198
- *
199
- * @param clientId - Client ID (JWT with prefix)
200
- * @param clientSecret - Client secret (optional for public clients)
201
- * @returns Whether credentials are valid
202
- */
197
+ * Validate client credentials (stateless)
198
+ *
199
+ * @param clientId - Client ID (JWT with prefix)
200
+ * @param clientSecret - Client secret (optional for public clients)
201
+ * @returns Whether credentials are valid
202
+ */
203
203
  validate(clientId, clientSecret) {
204
204
  try {
205
205
  const jwtWithoutPrefix = this.extractJWT(clientId);
@@ -216,8 +216,8 @@ var DynamicClientRegistration = class {
216
216
  }
217
217
  }
218
218
  /**
219
- * Get a registered client by ID (stateless)
220
- */
219
+ * Get a registered client by ID (stateless)
220
+ */
221
221
  getClient(clientId) {
222
222
  try {
223
223
  const jwtWithoutPrefix = this.extractJWT(clientId);
@@ -239,8 +239,8 @@ var DynamicClientRegistration = class {
239
239
  }
240
240
  }
241
241
  /**
242
- * Validate redirect URI for a client
243
- */
242
+ * Validate redirect URI for a client
243
+ */
244
244
  validateRedirectUri(clientId, redirectUri) {
245
245
  const client = this.getClient(clientId);
246
246
  if (!client) return false;
@@ -248,29 +248,29 @@ var DynamicClientRegistration = class {
248
248
  return client.redirect_uris.includes(redirectUri);
249
249
  }
250
250
  /**
251
- * Delete a client (no-op in stateless mode)
252
- *
253
- * In stateless mode, clients cannot be truly "deleted" because
254
- * their credentials are self-contained. They will expire naturally
255
- * or when the signing secret is rotated.
256
- */
251
+ * Delete a client (no-op in stateless mode)
252
+ *
253
+ * In stateless mode, clients cannot be truly "deleted" because
254
+ * their credentials are self-contained. They will expire naturally
255
+ * or when the signing secret is rotated.
256
+ */
257
257
  delete(clientId) {
258
258
  return this.getClient(clientId) !== void 0;
259
259
  }
260
260
  /**
261
- * List all registered clients (not supported in stateless mode)
262
- */
261
+ * List all registered clients (not supported in stateless mode)
262
+ */
263
263
  listClients() {
264
264
  throw new Error("listClients() is not supported in stateless DCR mode");
265
265
  }
266
266
  /**
267
- * Clear all clients (no-op in stateless mode)
268
- */
267
+ * Clear all clients (no-op in stateless mode)
268
+ */
269
269
  clearAll() {
270
270
  }
271
271
  /**
272
- * Extract JWT from prefixed client_id
273
- */
272
+ * Extract JWT from prefixed client_id
273
+ */
274
274
  extractJWT(clientId) {
275
275
  if (!clientId.startsWith(this.options.clientIdPrefix)) {
276
276
  return null;
@@ -278,11 +278,11 @@ var DynamicClientRegistration = class {
278
278
  return clientId.slice(this.options.clientIdPrefix.length);
279
279
  }
280
280
  /**
281
- * Derive client secret from client_id JWT
282
- *
283
- * Uses HMAC to create a deterministic secret that can be
284
- * validated without storage.
285
- */
281
+ * Derive client secret from client_id JWT
282
+ *
283
+ * Uses HMAC to create a deterministic secret that can be
284
+ * validated without storage.
285
+ */
286
286
  deriveClientSecret(clientIdJWT) {
287
287
  const { createHmac: createHmac3 } = require("crypto");
288
288
  return createHmac3("sha256", this.options.signingSecret).update(clientIdJWT).digest("hex");
@@ -331,16 +331,16 @@ var OAuthAuthorizationServer = class {
331
331
  });
332
332
  }
333
333
  /**
334
- * Generate state parameter with HMAC signature
335
- */
334
+ * Generate state parameter with HMAC signature
335
+ */
336
336
  generateState() {
337
337
  const nonce = (0, import_crypto3.randomUUID)();
338
338
  const signature = (0, import_crypto3.createHmac)("sha256", this.options.sessionSecret).update(nonce).digest("hex").substring(0, 8);
339
339
  return `${nonce}.${signature}`;
340
340
  }
341
341
  /**
342
- * Verify state parameter signature
343
- */
342
+ * Verify state parameter signature
343
+ */
344
344
  verifyState(state) {
345
345
  const [nonce, signature] = state.split(".");
346
346
  if (!nonce || !signature) return false;
@@ -348,14 +348,14 @@ var OAuthAuthorizationServer = class {
348
348
  return signature === expectedSignature;
349
349
  }
350
350
  /**
351
- * Generate an authorization code
352
- */
351
+ * Generate an authorization code
352
+ */
353
353
  generateAuthCode() {
354
354
  return (0, import_crypto3.randomBytes)(32).toString("hex");
355
355
  }
356
356
  /**
357
- * Generate JWT access token with encrypted upstream credentials
358
- */
357
+ * Generate JWT access token with encrypted upstream credentials
358
+ */
359
359
  generateAccessToken(claims, upstreamToken) {
360
360
  const now = Math.floor(Date.now() / 1e3);
361
361
  const jwtSigningSecret = this.options.jwtSigningSecret || this.options.sessionSecret;
@@ -382,8 +382,8 @@ var OAuthAuthorizationServer = class {
382
382
  return signJWT(payload, jwtSigningSecret);
383
383
  }
384
384
  /**
385
- * Get authorization server metadata (RFC 8414)
386
- */
385
+ * Get authorization server metadata (RFC 8414)
386
+ */
387
387
  getMetadata() {
388
388
  const issuer = this.options.issuer;
389
389
  return {
@@ -410,8 +410,8 @@ var OAuthAuthorizationServer = class {
410
410
  };
411
411
  }
412
412
  /**
413
- * Get Express router with all OAuth endpoints
414
- */
413
+ * Get Express router with all OAuth endpoints
414
+ */
415
415
  getRouter() {
416
416
  const router = import_express.default.Router();
417
417
  router.get("/.well-known/oauth-authorization-server", (_req, res) => {
@@ -444,8 +444,8 @@ var OAuthAuthorizationServer = class {
444
444
  return router;
445
445
  }
446
446
  /**
447
- * Handle authorization request
448
- */
447
+ * Handle authorization request
448
+ */
449
449
  handleAuthorize(req, res) {
450
450
  const { response_type, client_id, redirect_uri, scope, state, code_challenge, code_challenge_method, resource } = req.query;
451
451
  if (response_type !== "code") {
@@ -514,8 +514,8 @@ var OAuthAuthorizationServer = class {
514
514
  res.redirect(authUrl.toString());
515
515
  }
516
516
  /**
517
- * Handle callback from upstream provider
518
- */
517
+ * Handle callback from upstream provider
518
+ */
519
519
  async handleCallback(req, res) {
520
520
  const { code, state, error, error_description } = req.query;
521
521
  if (error) {
@@ -567,7 +567,7 @@ var OAuthAuthorizationServer = class {
567
567
  const tokenResponse = await fetch(upstream.tokenEndpoint, {
568
568
  method: "POST",
569
569
  headers: {
570
- "Accept": "application/json",
570
+ Accept: "application/json",
571
571
  "Content-Type": "application/x-www-form-urlencoded"
572
572
  },
573
573
  body: new URLSearchParams({
@@ -587,8 +587,8 @@ var OAuthAuthorizationServer = class {
587
587
  if (upstream.userInfoEndpoint && upstreamTokens.access_token) {
588
588
  const userInfoResponse = await fetch(upstream.userInfoEndpoint, {
589
589
  headers: {
590
- "Authorization": `Bearer ${upstreamTokens.access_token}`,
591
- "Accept": "application/json"
590
+ Authorization: `Bearer ${upstreamTokens.access_token}`,
591
+ Accept: "application/json"
592
592
  }
593
593
  });
594
594
  if (userInfoResponse.ok) {
@@ -625,8 +625,8 @@ var OAuthAuthorizationServer = class {
625
625
  }
626
626
  }
627
627
  /**
628
- * Handle token request
629
- */
628
+ * Handle token request
629
+ */
630
630
  async handleToken(req, res) {
631
631
  const { grant_type, code, redirect_uri, client_id, client_secret, code_verifier } = req.body;
632
632
  let clientId = client_id;
@@ -672,8 +672,8 @@ var OAuthAuthorizationServer = class {
672
672
  }
673
673
  }
674
674
  /**
675
- * Handle authorization code grant
676
- */
675
+ * Handle authorization code grant
676
+ */
677
677
  async handleAuthCodeGrant(res, clientId, code, redirectUri, codeVerifier) {
678
678
  if (!code) {
679
679
  res.status(400).json({
@@ -776,11 +776,11 @@ var TokenVerifier = class {
776
776
  };
777
777
  }
778
778
  /**
779
- * Verify a JWT access token
780
- *
781
- * @param token - The JWT access token to verify
782
- * @returns Verification result with claims and decrypted upstream token if valid
783
- */
779
+ * Verify a JWT access token
780
+ *
781
+ * @param token - The JWT access token to verify
782
+ * @returns Verification result with claims and decrypted upstream token if valid
783
+ */
784
784
  async verify(token) {
785
785
  if (!token) {
786
786
  return {
@@ -843,13 +843,13 @@ var TokenVerifier = class {
843
843
  }
844
844
  }
845
845
  /**
846
- * Generate WWW-Authenticate header for 401 responses
847
- *
848
- * Per RFC 9728, this should include the resource_metadata URL
849
- *
850
- * @param options - Header options
851
- * @returns WWW-Authenticate header value
852
- */
846
+ * Generate WWW-Authenticate header for 401 responses
847
+ *
848
+ * Per RFC 9728, this should include the resource_metadata URL
849
+ *
850
+ * @param options - Header options
851
+ * @returns WWW-Authenticate header value
852
+ */
853
853
  static getWWWAuthenticateHeader(options) {
854
854
  const parts = [
855
855
  `Bearer resource_metadata="${options.resourceMetadataUrl}"`
@@ -866,8 +866,8 @@ var TokenVerifier = class {
866
866
  return parts.join(", ");
867
867
  }
868
868
  /**
869
- * Check if token has required scopes
870
- */
869
+ * Check if token has required scopes
870
+ */
871
871
  hasScopes(claims, requiredScopes) {
872
872
  if (requiredScopes.length === 0) return true;
873
873
  const tokenScopes = typeof claims.scope === "string" ? claims.scope.split(" ") : claims.scope || [];
@@ -114,11 +114,11 @@ var DynamicClientRegistration = class {
114
114
  };
115
115
  }
116
116
  /**
117
- * Register a new OAuth client (stateless)
118
- *
119
- * @param request - Client registration request per RFC 7591
120
- * @returns Client registration response with JWT credentials
121
- */
117
+ * Register a new OAuth client (stateless)
118
+ *
119
+ * @param request - Client registration request per RFC 7591
120
+ * @returns Client registration response with JWT credentials
121
+ */
122
122
  register(request) {
123
123
  const now = Date.now();
124
124
  const nowSeconds = Math.floor(now / 1e3);
@@ -160,12 +160,12 @@ var DynamicClientRegistration = class {
160
160
  return response;
161
161
  }
162
162
  /**
163
- * Validate client credentials (stateless)
164
- *
165
- * @param clientId - Client ID (JWT with prefix)
166
- * @param clientSecret - Client secret (optional for public clients)
167
- * @returns Whether credentials are valid
168
- */
163
+ * Validate client credentials (stateless)
164
+ *
165
+ * @param clientId - Client ID (JWT with prefix)
166
+ * @param clientSecret - Client secret (optional for public clients)
167
+ * @returns Whether credentials are valid
168
+ */
169
169
  validate(clientId, clientSecret) {
170
170
  try {
171
171
  const jwtWithoutPrefix = this.extractJWT(clientId);
@@ -182,8 +182,8 @@ var DynamicClientRegistration = class {
182
182
  }
183
183
  }
184
184
  /**
185
- * Get a registered client by ID (stateless)
186
- */
185
+ * Get a registered client by ID (stateless)
186
+ */
187
187
  getClient(clientId) {
188
188
  try {
189
189
  const jwtWithoutPrefix = this.extractJWT(clientId);
@@ -205,8 +205,8 @@ var DynamicClientRegistration = class {
205
205
  }
206
206
  }
207
207
  /**
208
- * Validate redirect URI for a client
209
- */
208
+ * Validate redirect URI for a client
209
+ */
210
210
  validateRedirectUri(clientId, redirectUri) {
211
211
  const client = this.getClient(clientId);
212
212
  if (!client) return false;
@@ -214,29 +214,29 @@ var DynamicClientRegistration = class {
214
214
  return client.redirect_uris.includes(redirectUri);
215
215
  }
216
216
  /**
217
- * Delete a client (no-op in stateless mode)
218
- *
219
- * In stateless mode, clients cannot be truly "deleted" because
220
- * their credentials are self-contained. They will expire naturally
221
- * or when the signing secret is rotated.
222
- */
217
+ * Delete a client (no-op in stateless mode)
218
+ *
219
+ * In stateless mode, clients cannot be truly "deleted" because
220
+ * their credentials are self-contained. They will expire naturally
221
+ * or when the signing secret is rotated.
222
+ */
223
223
  delete(clientId) {
224
224
  return this.getClient(clientId) !== void 0;
225
225
  }
226
226
  /**
227
- * List all registered clients (not supported in stateless mode)
228
- */
227
+ * List all registered clients (not supported in stateless mode)
228
+ */
229
229
  listClients() {
230
230
  throw new Error("listClients() is not supported in stateless DCR mode");
231
231
  }
232
232
  /**
233
- * Clear all clients (no-op in stateless mode)
234
- */
233
+ * Clear all clients (no-op in stateless mode)
234
+ */
235
235
  clearAll() {
236
236
  }
237
237
  /**
238
- * Extract JWT from prefixed client_id
239
- */
238
+ * Extract JWT from prefixed client_id
239
+ */
240
240
  extractJWT(clientId) {
241
241
  if (!clientId.startsWith(this.options.clientIdPrefix)) {
242
242
  return null;
@@ -244,11 +244,11 @@ var DynamicClientRegistration = class {
244
244
  return clientId.slice(this.options.clientIdPrefix.length);
245
245
  }
246
246
  /**
247
- * Derive client secret from client_id JWT
248
- *
249
- * Uses HMAC to create a deterministic secret that can be
250
- * validated without storage.
251
- */
247
+ * Derive client secret from client_id JWT
248
+ *
249
+ * Uses HMAC to create a deterministic secret that can be
250
+ * validated without storage.
251
+ */
252
252
  deriveClientSecret(clientIdJWT) {
253
253
  const { createHmac: createHmac3 } = __require("crypto");
254
254
  return createHmac3("sha256", this.options.signingSecret).update(clientIdJWT).digest("hex");
@@ -297,16 +297,16 @@ var OAuthAuthorizationServer = class {
297
297
  });
298
298
  }
299
299
  /**
300
- * Generate state parameter with HMAC signature
301
- */
300
+ * Generate state parameter with HMAC signature
301
+ */
302
302
  generateState() {
303
303
  const nonce = randomUUID2();
304
304
  const signature = createHmac2("sha256", this.options.sessionSecret).update(nonce).digest("hex").substring(0, 8);
305
305
  return `${nonce}.${signature}`;
306
306
  }
307
307
  /**
308
- * Verify state parameter signature
309
- */
308
+ * Verify state parameter signature
309
+ */
310
310
  verifyState(state) {
311
311
  const [nonce, signature] = state.split(".");
312
312
  if (!nonce || !signature) return false;
@@ -314,14 +314,14 @@ var OAuthAuthorizationServer = class {
314
314
  return signature === expectedSignature;
315
315
  }
316
316
  /**
317
- * Generate an authorization code
318
- */
317
+ * Generate an authorization code
318
+ */
319
319
  generateAuthCode() {
320
320
  return randomBytes2(32).toString("hex");
321
321
  }
322
322
  /**
323
- * Generate JWT access token with encrypted upstream credentials
324
- */
323
+ * Generate JWT access token with encrypted upstream credentials
324
+ */
325
325
  generateAccessToken(claims, upstreamToken) {
326
326
  const now = Math.floor(Date.now() / 1e3);
327
327
  const jwtSigningSecret = this.options.jwtSigningSecret || this.options.sessionSecret;
@@ -348,8 +348,8 @@ var OAuthAuthorizationServer = class {
348
348
  return signJWT(payload, jwtSigningSecret);
349
349
  }
350
350
  /**
351
- * Get authorization server metadata (RFC 8414)
352
- */
351
+ * Get authorization server metadata (RFC 8414)
352
+ */
353
353
  getMetadata() {
354
354
  const issuer = this.options.issuer;
355
355
  return {
@@ -376,8 +376,8 @@ var OAuthAuthorizationServer = class {
376
376
  };
377
377
  }
378
378
  /**
379
- * Get Express router with all OAuth endpoints
380
- */
379
+ * Get Express router with all OAuth endpoints
380
+ */
381
381
  getRouter() {
382
382
  const router = express.Router();
383
383
  router.get("/.well-known/oauth-authorization-server", (_req, res) => {
@@ -410,8 +410,8 @@ var OAuthAuthorizationServer = class {
410
410
  return router;
411
411
  }
412
412
  /**
413
- * Handle authorization request
414
- */
413
+ * Handle authorization request
414
+ */
415
415
  handleAuthorize(req, res) {
416
416
  const { response_type, client_id, redirect_uri, scope, state, code_challenge, code_challenge_method, resource } = req.query;
417
417
  if (response_type !== "code") {
@@ -480,8 +480,8 @@ var OAuthAuthorizationServer = class {
480
480
  res.redirect(authUrl.toString());
481
481
  }
482
482
  /**
483
- * Handle callback from upstream provider
484
- */
483
+ * Handle callback from upstream provider
484
+ */
485
485
  async handleCallback(req, res) {
486
486
  const { code, state, error, error_description } = req.query;
487
487
  if (error) {
@@ -533,7 +533,7 @@ var OAuthAuthorizationServer = class {
533
533
  const tokenResponse = await fetch(upstream.tokenEndpoint, {
534
534
  method: "POST",
535
535
  headers: {
536
- "Accept": "application/json",
536
+ Accept: "application/json",
537
537
  "Content-Type": "application/x-www-form-urlencoded"
538
538
  },
539
539
  body: new URLSearchParams({
@@ -553,8 +553,8 @@ var OAuthAuthorizationServer = class {
553
553
  if (upstream.userInfoEndpoint && upstreamTokens.access_token) {
554
554
  const userInfoResponse = await fetch(upstream.userInfoEndpoint, {
555
555
  headers: {
556
- "Authorization": `Bearer ${upstreamTokens.access_token}`,
557
- "Accept": "application/json"
556
+ Authorization: `Bearer ${upstreamTokens.access_token}`,
557
+ Accept: "application/json"
558
558
  }
559
559
  });
560
560
  if (userInfoResponse.ok) {
@@ -591,8 +591,8 @@ var OAuthAuthorizationServer = class {
591
591
  }
592
592
  }
593
593
  /**
594
- * Handle token request
595
- */
594
+ * Handle token request
595
+ */
596
596
  async handleToken(req, res) {
597
597
  const { grant_type, code, redirect_uri, client_id, client_secret, code_verifier } = req.body;
598
598
  let clientId = client_id;
@@ -638,8 +638,8 @@ var OAuthAuthorizationServer = class {
638
638
  }
639
639
  }
640
640
  /**
641
- * Handle authorization code grant
642
- */
641
+ * Handle authorization code grant
642
+ */
643
643
  async handleAuthCodeGrant(res, clientId, code, redirectUri, codeVerifier) {
644
644
  if (!code) {
645
645
  res.status(400).json({
@@ -742,11 +742,11 @@ var TokenVerifier = class {
742
742
  };
743
743
  }
744
744
  /**
745
- * Verify a JWT access token
746
- *
747
- * @param token - The JWT access token to verify
748
- * @returns Verification result with claims and decrypted upstream token if valid
749
- */
745
+ * Verify a JWT access token
746
+ *
747
+ * @param token - The JWT access token to verify
748
+ * @returns Verification result with claims and decrypted upstream token if valid
749
+ */
750
750
  async verify(token) {
751
751
  if (!token) {
752
752
  return {
@@ -809,13 +809,13 @@ var TokenVerifier = class {
809
809
  }
810
810
  }
811
811
  /**
812
- * Generate WWW-Authenticate header for 401 responses
813
- *
814
- * Per RFC 9728, this should include the resource_metadata URL
815
- *
816
- * @param options - Header options
817
- * @returns WWW-Authenticate header value
818
- */
812
+ * Generate WWW-Authenticate header for 401 responses
813
+ *
814
+ * Per RFC 9728, this should include the resource_metadata URL
815
+ *
816
+ * @param options - Header options
817
+ * @returns WWW-Authenticate header value
818
+ */
819
819
  static getWWWAuthenticateHeader(options) {
820
820
  const parts = [
821
821
  `Bearer resource_metadata="${options.resourceMetadataUrl}"`
@@ -832,8 +832,8 @@ var TokenVerifier = class {
832
832
  return parts.join(", ");
833
833
  }
834
834
  /**
835
- * Check if token has required scopes
836
- */
835
+ * Check if token has required scopes
836
+ */
837
837
  hasScopes(claims, requiredScopes) {
838
838
  if (requiredScopes.length === 0) return true;
839
839
  const tokenScopes = typeof claims.scope === "string" ? claims.scope.split(" ") : claims.scope || [];