@leanmcp/auth 0.4.3 → 0.4.4-alpha.8.f4673cd

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.
@@ -233,28 +233,28 @@ var OAuthProxy = class {
233
233
  }
234
234
  }
235
235
  /**
236
- * Get configured providers
237
- */
236
+ * Get configured providers
237
+ */
238
238
  getProviders() {
239
239
  return this.config.providers;
240
240
  }
241
241
  /**
242
- * Get a provider by ID
243
- */
242
+ * Get a provider by ID
243
+ */
244
244
  getProvider(id) {
245
245
  return this.providersMap.get(id);
246
246
  }
247
247
  /**
248
- * Generate state parameter with signature
249
- */
248
+ * Generate state parameter with signature
249
+ */
250
250
  generateState() {
251
251
  const nonce = (0, import_crypto2.randomUUID)();
252
252
  const signature = (0, import_crypto2.createHmac)("sha256", this.config.sessionSecret).update(nonce).digest("hex").substring(0, 8);
253
253
  return `${nonce}.${signature}`;
254
254
  }
255
255
  /**
256
- * Verify state parameter signature
257
- */
256
+ * Verify state parameter signature
257
+ */
258
258
  verifyState(state) {
259
259
  const [nonce, signature] = state.split(".");
260
260
  if (!nonce || !signature) return false;
@@ -262,13 +262,13 @@ var OAuthProxy = class {
262
262
  return signature === expectedSignature;
263
263
  }
264
264
  /**
265
- * Handle authorization request
266
- *
267
- * Redirects the user to the external provider's authorization page.
268
- *
269
- * @param params - Request parameters
270
- * @returns URL to redirect the user to
271
- */
265
+ * Handle authorization request
266
+ *
267
+ * Redirects the user to the external provider's authorization page.
268
+ *
269
+ * @param params - Request parameters
270
+ * @returns URL to redirect the user to
271
+ */
272
272
  handleAuthorize(params) {
273
273
  const provider = this.providersMap.get(params.provider);
274
274
  if (!provider) {
@@ -311,13 +311,13 @@ var OAuthProxy = class {
311
311
  return authUrl.toString();
312
312
  }
313
313
  /**
314
- * Handle callback from external provider
315
- *
316
- * Exchanges the authorization code for tokens and maps them.
317
- *
318
- * @param params - Callback query parameters
319
- * @returns Result with redirect URI and tokens
320
- */
314
+ * Handle callback from external provider
315
+ *
316
+ * Exchanges the authorization code for tokens and maps them.
317
+ *
318
+ * @param params - Callback query parameters
319
+ * @returns Result with redirect URI and tokens
320
+ */
321
321
  async handleCallback(params) {
322
322
  const { code, state, error, error_description } = params;
323
323
  if (error) {
@@ -372,8 +372,8 @@ var OAuthProxy = class {
372
372
  };
373
373
  }
374
374
  /**
375
- * Exchange authorization code for tokens with external provider
376
- */
375
+ * Exchange authorization code for tokens with external provider
376
+ */
377
377
  async exchangeCodeForTokens(provider, code, redirectUri, codeVerifier) {
378
378
  const tokenPayload = {
379
379
  grant_type: "authorization_code",
@@ -394,7 +394,7 @@ var OAuthProxy = class {
394
394
  }
395
395
  const headers = {
396
396
  "Content-Type": "application/x-www-form-urlencoded",
397
- "Accept": "application/json"
397
+ Accept: "application/json"
398
398
  };
399
399
  if (provider.tokenEndpointAuthMethod === "client_secret_basic") {
400
400
  const credentials = Buffer.from(`${provider.clientId}:${provider.clientSecret}`).toString("base64");
@@ -412,8 +412,8 @@ var OAuthProxy = class {
412
412
  return response.json();
413
413
  }
414
414
  /**
415
- * Fetch user info from external provider
416
- */
415
+ * Fetch user info from external provider
416
+ */
417
417
  async fetchUserInfo(provider, accessToken) {
418
418
  if (!provider.userInfoEndpoint) {
419
419
  return {
@@ -422,8 +422,8 @@ var OAuthProxy = class {
422
422
  }
423
423
  const response = await fetch(provider.userInfoEndpoint, {
424
424
  headers: {
425
- "Authorization": `Bearer ${accessToken}`,
426
- "Accept": "application/json"
425
+ Authorization: `Bearer ${accessToken}`,
426
+ Accept: "application/json"
427
427
  }
428
428
  });
429
429
  if (!response.ok) {
@@ -443,9 +443,9 @@ var OAuthProxy = class {
443
443
  };
444
444
  }
445
445
  /**
446
- * Generate an internal authorization code for the mapped tokens
447
- * This code can be exchanged via the token endpoint
448
- */
446
+ * Generate an internal authorization code for the mapped tokens
447
+ * This code can be exchanged via the token endpoint
448
+ */
449
449
  generateInternalCode(tokens) {
450
450
  const code = (0, import_crypto2.randomUUID)();
451
451
  const signature = (0, import_crypto2.createHmac)("sha256", this.config.sessionSecret).update(code).update(JSON.stringify(tokens)).digest("hex").substring(0, 16);
@@ -462,8 +462,8 @@ var OAuthProxy = class {
462
462
  return fullCode;
463
463
  }
464
464
  /**
465
- * Handle token request (exchange internal code for tokens)
466
- */
465
+ * Handle token request (exchange internal code for tokens)
466
+ */
467
467
  async handleToken(params) {
468
468
  const { grant_type, code, refresh_token } = params;
469
469
  if (grant_type === "authorization_code") {
@@ -486,8 +486,8 @@ var OAuthProxy = class {
486
486
  throw new Error(`Unsupported grant_type: ${grant_type}`);
487
487
  }
488
488
  /**
489
- * Express/Connect middleware factory
490
- */
489
+ * Express/Connect middleware factory
490
+ */
491
491
  createMiddleware() {
492
492
  return {
493
493
  authorize: /* @__PURE__ */ __name((req, res) => {
@@ -178,28 +178,28 @@ var OAuthProxy = class {
178
178
  }
179
179
  }
180
180
  /**
181
- * Get configured providers
182
- */
181
+ * Get configured providers
182
+ */
183
183
  getProviders() {
184
184
  return this.config.providers;
185
185
  }
186
186
  /**
187
- * Get a provider by ID
188
- */
187
+ * Get a provider by ID
188
+ */
189
189
  getProvider(id) {
190
190
  return this.providersMap.get(id);
191
191
  }
192
192
  /**
193
- * Generate state parameter with signature
194
- */
193
+ * Generate state parameter with signature
194
+ */
195
195
  generateState() {
196
196
  const nonce = randomUUID();
197
197
  const signature = createHmac("sha256", this.config.sessionSecret).update(nonce).digest("hex").substring(0, 8);
198
198
  return `${nonce}.${signature}`;
199
199
  }
200
200
  /**
201
- * Verify state parameter signature
202
- */
201
+ * Verify state parameter signature
202
+ */
203
203
  verifyState(state) {
204
204
  const [nonce, signature] = state.split(".");
205
205
  if (!nonce || !signature) return false;
@@ -207,13 +207,13 @@ var OAuthProxy = class {
207
207
  return signature === expectedSignature;
208
208
  }
209
209
  /**
210
- * Handle authorization request
211
- *
212
- * Redirects the user to the external provider's authorization page.
213
- *
214
- * @param params - Request parameters
215
- * @returns URL to redirect the user to
216
- */
210
+ * Handle authorization request
211
+ *
212
+ * Redirects the user to the external provider's authorization page.
213
+ *
214
+ * @param params - Request parameters
215
+ * @returns URL to redirect the user to
216
+ */
217
217
  handleAuthorize(params) {
218
218
  const provider = this.providersMap.get(params.provider);
219
219
  if (!provider) {
@@ -256,13 +256,13 @@ var OAuthProxy = class {
256
256
  return authUrl.toString();
257
257
  }
258
258
  /**
259
- * Handle callback from external provider
260
- *
261
- * Exchanges the authorization code for tokens and maps them.
262
- *
263
- * @param params - Callback query parameters
264
- * @returns Result with redirect URI and tokens
265
- */
259
+ * Handle callback from external provider
260
+ *
261
+ * Exchanges the authorization code for tokens and maps them.
262
+ *
263
+ * @param params - Callback query parameters
264
+ * @returns Result with redirect URI and tokens
265
+ */
266
266
  async handleCallback(params) {
267
267
  const { code, state, error, error_description } = params;
268
268
  if (error) {
@@ -317,8 +317,8 @@ var OAuthProxy = class {
317
317
  };
318
318
  }
319
319
  /**
320
- * Exchange authorization code for tokens with external provider
321
- */
320
+ * Exchange authorization code for tokens with external provider
321
+ */
322
322
  async exchangeCodeForTokens(provider, code, redirectUri, codeVerifier) {
323
323
  const tokenPayload = {
324
324
  grant_type: "authorization_code",
@@ -339,7 +339,7 @@ var OAuthProxy = class {
339
339
  }
340
340
  const headers = {
341
341
  "Content-Type": "application/x-www-form-urlencoded",
342
- "Accept": "application/json"
342
+ Accept: "application/json"
343
343
  };
344
344
  if (provider.tokenEndpointAuthMethod === "client_secret_basic") {
345
345
  const credentials = Buffer.from(`${provider.clientId}:${provider.clientSecret}`).toString("base64");
@@ -357,8 +357,8 @@ var OAuthProxy = class {
357
357
  return response.json();
358
358
  }
359
359
  /**
360
- * Fetch user info from external provider
361
- */
360
+ * Fetch user info from external provider
361
+ */
362
362
  async fetchUserInfo(provider, accessToken) {
363
363
  if (!provider.userInfoEndpoint) {
364
364
  return {
@@ -367,8 +367,8 @@ var OAuthProxy = class {
367
367
  }
368
368
  const response = await fetch(provider.userInfoEndpoint, {
369
369
  headers: {
370
- "Authorization": `Bearer ${accessToken}`,
371
- "Accept": "application/json"
370
+ Authorization: `Bearer ${accessToken}`,
371
+ Accept: "application/json"
372
372
  }
373
373
  });
374
374
  if (!response.ok) {
@@ -388,9 +388,9 @@ var OAuthProxy = class {
388
388
  };
389
389
  }
390
390
  /**
391
- * Generate an internal authorization code for the mapped tokens
392
- * This code can be exchanged via the token endpoint
393
- */
391
+ * Generate an internal authorization code for the mapped tokens
392
+ * This code can be exchanged via the token endpoint
393
+ */
394
394
  generateInternalCode(tokens) {
395
395
  const code = randomUUID();
396
396
  const signature = createHmac("sha256", this.config.sessionSecret).update(code).update(JSON.stringify(tokens)).digest("hex").substring(0, 16);
@@ -407,8 +407,8 @@ var OAuthProxy = class {
407
407
  return fullCode;
408
408
  }
409
409
  /**
410
- * Handle token request (exchange internal code for tokens)
411
- */
410
+ * Handle token request (exchange internal code for tokens)
411
+ */
412
412
  async handleToken(params) {
413
413
  const { grant_type, code, refresh_token } = params;
414
414
  if (grant_type === "authorization_code") {
@@ -431,8 +431,8 @@ var OAuthProxy = class {
431
431
  throw new Error(`Unsupported grant_type: ${grant_type}`);
432
432
  }
433
433
  /**
434
- * Express/Connect middleware factory
435
- */
434
+ * Express/Connect middleware factory
435
+ */
436
436
  createMiddleware() {
437
437
  return {
438
438
  authorize: /* @__PURE__ */ __name((req, res) => {
@@ -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 || [];