fastmcp 4.9.0 → 4.9.1

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/README.md CHANGED
@@ -1951,14 +1951,9 @@ const server = new FastMCP({
1951
1951
  FastMCP also supports OAuth discovery endpoints for direct integration with OAuth providers, supporting both **MCP Specification 2025-03-26** and **MCP Specification 2025-06-18**. This provides standard discovery endpoints that comply with RFC 8414 (OAuth 2.0 Authorization Server Metadata) and RFC 9470 (OAuth 2.0 Protected Resource Metadata):
1952
1952
 
1953
1953
  ```ts
1954
- import { FastMCP, DiscoveryDocumentCache } from "fastmcp";
1955
- import { buildGetJwks } from "get-jwks";
1956
- import fastJwt from "fast-jwt";
1957
-
1958
- // Create a cache for discovery documents (reuse across requests)
1959
- const discoveryCache = new DiscoveryDocumentCache({
1960
- ttl: 3600000, // Cache for 1 hour (default)
1961
- });
1954
+ import { FastMCP } from "fastmcp";
1955
+ import buildGetJwks from "get-jwks";
1956
+ import fastJwt, { type DecodedJwt } from "fast-jwt";
1962
1957
 
1963
1958
  const server = new FastMCP({
1964
1959
  name: "My Server",
@@ -1991,39 +1986,20 @@ const server = new FastMCP({
1991
1986
 
1992
1987
  // Validate OAuth JWT access token using OpenID Connect discovery
1993
1988
  try {
1994
- // Fetch and cache the discovery document
1995
- const discoveryUrl =
1996
- "https://auth.example.com/.well-known/openid-configuration";
1997
- // Alternative: Use OAuth authorization server metadata endpoint
1998
- // const discoveryUrl = 'https://auth.example.com/.well-known/oauth-authorization-server';
1999
-
2000
- const config = (await discoveryCache.get(discoveryUrl)) as {
2001
- jwks_uri: string;
2002
- issuer: string;
2003
- };
2004
- const jwksUri = config.jwks_uri;
2005
- const issuer = config.issuer;
2006
-
2007
- // Create JWKS client for token verification using discovered endpoint
2008
- const getJwks = buildGetJwks({
2009
- jwksUrl: jwksUri,
2010
- cache: true,
2011
- rateLimit: true,
2012
- });
1989
+ // Create JWKS client for token verification
1990
+ const getJwks = buildGetJwks();
2013
1991
 
2014
- // Create JWT verifier with JWKS and discovered issuer
1992
+ // Create JWT verifier
2015
1993
  const verify = fastJwt.createVerifier({
2016
- key: async (token) => {
2017
- const { header } = fastJwt.decode(token, { complete: true });
2018
- const jwk = await getJwks.getJwk({
1994
+ async key({ header }: DecodedJwt) {
1995
+ const publicKey = await getJwks.getPublicKey({
2019
1996
  kid: header.kid,
2020
1997
  alg: header.alg,
1998
+ domain: "https://auth.example.com",
2021
1999
  });
2022
- return jwk;
2000
+ return publicKey;
2023
2001
  },
2024
- algorithms: ["RS256", "ES256"],
2025
- issuer: issuer,
2026
- audience: "mcp://my-server",
2002
+ algorithms: ["RS256"],
2027
2003
  });
2028
2004
 
2029
2005
  // Verify the JWT token
@@ -2081,7 +2057,7 @@ Clients discover protected resource metadata using the following search order:
2081
2057
 
2082
2058
  Both the sub-path and root endpoints return identical metadata, ensuring compatibility with all MCP client implementations.
2083
2059
 
2084
- For JWT token validation, you can use libraries like [`get-jwks`](https://github.com/nearform/get-jwks) and [`@fastify/jwt`](https://github.com/fastify/fastify-jwt) for OAuth JWT tokens.
2060
+ For JWT token validation, you can use libraries like [`get-jwks`](https://github.com/nearform/get-jwks) and [`fast-jwt`](https://github.com/nearform/fast-jwt) for OAuth JWT tokens.
2085
2061
 
2086
2062
  #### Passing Headers Through Context
2087
2063
 
package/dist/FastMCP.cjs CHANGED
@@ -20,7 +20,7 @@ var _chunkMJCWKCHZcjs = require('./chunk-MJCWKCHZ.cjs');
20
20
 
21
21
 
22
22
 
23
- var _chunkIX3HKAX4cjs = require('./chunk-IX3HKAX4.cjs');
23
+ var _chunkDZYT6QAHcjs = require('./chunk-DZYT6QAH.cjs');
24
24
 
25
25
 
26
26
 
@@ -41,5 +41,5 @@ var _chunkIX3HKAX4cjs = require('./chunk-IX3HKAX4.cjs');
41
41
 
42
42
 
43
43
 
44
- exports.AuthProvider = _chunkIX3HKAX4cjs.AuthProvider; exports.AzureProvider = _chunkIX3HKAX4cjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkMJCWKCHZcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkMJCWKCHZcjs.FastMCP; exports.FastMCPSession = _chunkMJCWKCHZcjs.FastMCPSession; exports.GitHubProvider = _chunkIX3HKAX4cjs.GitHubProvider; exports.GoogleProvider = _chunkIX3HKAX4cjs.GoogleProvider; exports.OAuthProvider = _chunkIX3HKAX4cjs.OAuthProvider; exports.ServerState = _chunkMJCWKCHZcjs.ServerState; exports.UnexpectedStateError = _chunkMJCWKCHZcjs.UnexpectedStateError; exports.UserError = _chunkMJCWKCHZcjs.UserError; exports.audioContent = _chunkMJCWKCHZcjs.audioContent; exports.getAuthSession = _chunkIX3HKAX4cjs.getAuthSession; exports.imageContent = _chunkMJCWKCHZcjs.imageContent; exports.requireAll = _chunkIX3HKAX4cjs.requireAll; exports.requireAny = _chunkIX3HKAX4cjs.requireAny; exports.requireAuth = _chunkIX3HKAX4cjs.requireAuth; exports.requireRole = _chunkIX3HKAX4cjs.requireRole; exports.requireScopes = _chunkIX3HKAX4cjs.requireScopes;
44
+ exports.AuthProvider = _chunkDZYT6QAHcjs.AuthProvider; exports.AzureProvider = _chunkDZYT6QAHcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkMJCWKCHZcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkMJCWKCHZcjs.FastMCP; exports.FastMCPSession = _chunkMJCWKCHZcjs.FastMCPSession; exports.GitHubProvider = _chunkDZYT6QAHcjs.GitHubProvider; exports.GoogleProvider = _chunkDZYT6QAHcjs.GoogleProvider; exports.OAuthProvider = _chunkDZYT6QAHcjs.OAuthProvider; exports.ServerState = _chunkMJCWKCHZcjs.ServerState; exports.UnexpectedStateError = _chunkMJCWKCHZcjs.UnexpectedStateError; exports.UserError = _chunkMJCWKCHZcjs.UserError; exports.audioContent = _chunkMJCWKCHZcjs.audioContent; exports.getAuthSession = _chunkDZYT6QAHcjs.getAuthSession; exports.imageContent = _chunkMJCWKCHZcjs.imageContent; exports.requireAll = _chunkDZYT6QAHcjs.requireAll; exports.requireAny = _chunkDZYT6QAHcjs.requireAny; exports.requireAuth = _chunkDZYT6QAHcjs.requireAuth; exports.requireRole = _chunkDZYT6QAHcjs.requireRole; exports.requireScopes = _chunkDZYT6QAHcjs.requireScopes;
45
45
  //# sourceMappingURL=FastMCP.cjs.map
@@ -12,8 +12,8 @@ import { CorsOptions } from 'mcp-proxy';
12
12
  export { CorsOptions } from 'mcp-proxy';
13
13
  import { StrictEventEmitter } from 'strict-event-emitter-types';
14
14
  import { z } from 'zod';
15
- import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-vyjR-9Z7.cjs';
16
- export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-vyjR-9Z7.cjs';
15
+ import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-BNqoBTYA.cjs';
16
+ export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-BNqoBTYA.cjs';
17
17
  import 'node:http';
18
18
 
19
19
  declare class DiscoveryDocumentCache {
package/dist/FastMCP.d.ts CHANGED
@@ -12,8 +12,8 @@ import { CorsOptions } from 'mcp-proxy';
12
12
  export { CorsOptions } from 'mcp-proxy';
13
13
  import { StrictEventEmitter } from 'strict-event-emitter-types';
14
14
  import { z } from 'zod';
15
- import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-vyjR-9Z7.js';
16
- export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-vyjR-9Z7.js';
15
+ import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-BNqoBTYA.js';
16
+ export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-BNqoBTYA.js';
17
17
  import 'node:http';
18
18
 
19
19
  declare class DiscoveryDocumentCache {
package/dist/FastMCP.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  requireAuth,
21
21
  requireRole,
22
22
  requireScopes
23
- } from "./chunk-OJG4XYXA.js";
23
+ } from "./chunk-GM44BOI7.js";
24
24
  export {
25
25
  AuthProvider,
26
26
  AzureProvider,
@@ -382,6 +382,21 @@ interface TokenStorage {
382
382
  get(key: string): Promise<null | unknown>;
383
383
  /** Save a value with optional TTL */
384
384
  save(key: string, value: unknown, ttl?: number): Promise<void>;
385
+ /**
386
+ * Atomically retrieve a value and delete it, returning `null` if the key was
387
+ * absent. At most one caller may observe a given value.
388
+ *
389
+ * Optional, but **required for correctness when more than one process shares
390
+ * this storage**: the OAuth proxy consumes authorization codes and
391
+ * transactions through it, and single-use enforcement depends on the
392
+ * atomicity. Without it the proxy falls back to a non-atomic get + delete,
393
+ * where two concurrent requests can both redeem the same authorization code.
394
+ *
395
+ * Most backends expose a suitable primitive: Redis `GETDEL`, DynamoDB
396
+ * `DeleteItem` with `ReturnValues: "ALL_OLD"`, or SQL
397
+ * `DELETE ... RETURNING *`.
398
+ */
399
+ take?(key: string): Promise<null | unknown>;
385
400
  }
386
401
  /**
387
402
  * Token verification result
@@ -431,16 +446,18 @@ interface UpstreamTokenSet {
431
446
  declare class OAuthProxy {
432
447
  private claimsExtractor;
433
448
  private cleanupInterval;
434
- private clientCodes;
435
449
  private config;
436
450
  private consentManager;
437
451
  private jwtIssuer?;
438
- /** Keyed by redirect_uri for defence-in-depth checks in handleCallback/handleConsent */
439
- private registeredClients;
440
- /** Keyed by proxy-issued client_id for authorize/token-exchange lookups */
452
+ /**
453
+ * Keyed by proxy-issued client_id for authorize/token-exchange lookups and
454
+ * for the defence-in-depth callback checks. A registration never changes
455
+ * after it is written, so caching it locally cannot go stale; it is also
456
+ * persisted, so another instance can hydrate it.
457
+ */
441
458
  private registeredClientsByClientId;
459
+ private stateStore;
442
460
  private tokenStorage;
443
- private transactions;
444
461
  constructor(config: OAuthProxyConfig);
445
462
  /**
446
463
  * OAuth authorization endpoint
@@ -503,7 +520,7 @@ declare class OAuthProxy {
503
520
  */
504
521
  private calculateAccessTokenTtl;
505
522
  /**
506
- * Clean up expired transactions and codes
523
+ * Periodic maintenance hook. Expiry is enforced by the token storage.
507
524
  */
508
525
  private cleanup;
509
526
  /**
@@ -382,6 +382,21 @@ interface TokenStorage {
382
382
  get(key: string): Promise<null | unknown>;
383
383
  /** Save a value with optional TTL */
384
384
  save(key: string, value: unknown, ttl?: number): Promise<void>;
385
+ /**
386
+ * Atomically retrieve a value and delete it, returning `null` if the key was
387
+ * absent. At most one caller may observe a given value.
388
+ *
389
+ * Optional, but **required for correctness when more than one process shares
390
+ * this storage**: the OAuth proxy consumes authorization codes and
391
+ * transactions through it, and single-use enforcement depends on the
392
+ * atomicity. Without it the proxy falls back to a non-atomic get + delete,
393
+ * where two concurrent requests can both redeem the same authorization code.
394
+ *
395
+ * Most backends expose a suitable primitive: Redis `GETDEL`, DynamoDB
396
+ * `DeleteItem` with `ReturnValues: "ALL_OLD"`, or SQL
397
+ * `DELETE ... RETURNING *`.
398
+ */
399
+ take?(key: string): Promise<null | unknown>;
385
400
  }
386
401
  /**
387
402
  * Token verification result
@@ -431,16 +446,18 @@ interface UpstreamTokenSet {
431
446
  declare class OAuthProxy {
432
447
  private claimsExtractor;
433
448
  private cleanupInterval;
434
- private clientCodes;
435
449
  private config;
436
450
  private consentManager;
437
451
  private jwtIssuer?;
438
- /** Keyed by redirect_uri for defence-in-depth checks in handleCallback/handleConsent */
439
- private registeredClients;
440
- /** Keyed by proxy-issued client_id for authorize/token-exchange lookups */
452
+ /**
453
+ * Keyed by proxy-issued client_id for authorize/token-exchange lookups and
454
+ * for the defence-in-depth callback checks. A registration never changes
455
+ * after it is written, so caching it locally cannot go stale; it is also
456
+ * persisted, so another instance can hydrate it.
457
+ */
441
458
  private registeredClientsByClientId;
459
+ private stateStore;
442
460
  private tokenStorage;
443
- private transactions;
444
461
  constructor(config: OAuthProxyConfig);
445
462
  /**
446
463
  * OAuth authorization endpoint
@@ -503,7 +520,7 @@ declare class OAuthProxy {
503
520
  */
504
521
  private calculateAccessTokenTtl;
505
522
  /**
506
- * Clean up expired transactions and codes
523
+ * Periodic maintenance hook. Expiry is enforced by the token storage.
507
524
  */
508
525
  private cleanup;
509
526
  /**
@@ -24,7 +24,7 @@
24
24
 
25
25
 
26
26
 
27
- var _chunkIX3HKAX4cjs = require('../chunk-IX3HKAX4.cjs');
27
+ var _chunkDZYT6QAHcjs = require('../chunk-DZYT6QAH.cjs');
28
28
 
29
29
 
30
30
 
@@ -51,5 +51,5 @@ var _chunkIX3HKAX4cjs = require('../chunk-IX3HKAX4.cjs');
51
51
 
52
52
 
53
53
 
54
- exports.AuthProvider = _chunkIX3HKAX4cjs.AuthProvider; exports.AzureProvider = _chunkIX3HKAX4cjs.AzureProvider; exports.ConsentManager = _chunkIX3HKAX4cjs.ConsentManager; exports.DEFAULT_ACCESS_TOKEN_TTL = _chunkIX3HKAX4cjs.DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = _chunkIX3HKAX4cjs.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_AUTHORIZATION_CODE_TTL = _chunkIX3HKAX4cjs.DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_REFRESH_TOKEN_TTL = _chunkIX3HKAX4cjs.DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_TRANSACTION_TTL = _chunkIX3HKAX4cjs.DEFAULT_TRANSACTION_TTL; exports.DiskStore = _chunkIX3HKAX4cjs.DiskStore; exports.EncryptedTokenStorage = _chunkIX3HKAX4cjs.EncryptedTokenStorage; exports.GitHubProvider = _chunkIX3HKAX4cjs.GitHubProvider; exports.GoogleProvider = _chunkIX3HKAX4cjs.GoogleProvider; exports.JWKSVerifier = _chunkIX3HKAX4cjs.JWKSVerifier; exports.JWTIssuer = _chunkIX3HKAX4cjs.JWTIssuer; exports.MemoryTokenStorage = _chunkIX3HKAX4cjs.MemoryTokenStorage; exports.OAuthProvider = _chunkIX3HKAX4cjs.OAuthProvider; exports.OAuthProxy = _chunkIX3HKAX4cjs.OAuthProxy; exports.OAuthProxyError = _chunkIX3HKAX4cjs.OAuthProxyError; exports.PKCEUtils = _chunkIX3HKAX4cjs.PKCEUtils; exports.getAuthSession = _chunkIX3HKAX4cjs.getAuthSession; exports.requireAll = _chunkIX3HKAX4cjs.requireAll; exports.requireAny = _chunkIX3HKAX4cjs.requireAny; exports.requireAuth = _chunkIX3HKAX4cjs.requireAuth; exports.requireRole = _chunkIX3HKAX4cjs.requireRole; exports.requireScopes = _chunkIX3HKAX4cjs.requireScopes;
54
+ exports.AuthProvider = _chunkDZYT6QAHcjs.AuthProvider; exports.AzureProvider = _chunkDZYT6QAHcjs.AzureProvider; exports.ConsentManager = _chunkDZYT6QAHcjs.ConsentManager; exports.DEFAULT_ACCESS_TOKEN_TTL = _chunkDZYT6QAHcjs.DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = _chunkDZYT6QAHcjs.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_AUTHORIZATION_CODE_TTL = _chunkDZYT6QAHcjs.DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_REFRESH_TOKEN_TTL = _chunkDZYT6QAHcjs.DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_TRANSACTION_TTL = _chunkDZYT6QAHcjs.DEFAULT_TRANSACTION_TTL; exports.DiskStore = _chunkDZYT6QAHcjs.DiskStore; exports.EncryptedTokenStorage = _chunkDZYT6QAHcjs.EncryptedTokenStorage; exports.GitHubProvider = _chunkDZYT6QAHcjs.GitHubProvider; exports.GoogleProvider = _chunkDZYT6QAHcjs.GoogleProvider; exports.JWKSVerifier = _chunkDZYT6QAHcjs.JWKSVerifier; exports.JWTIssuer = _chunkDZYT6QAHcjs.JWTIssuer; exports.MemoryTokenStorage = _chunkDZYT6QAHcjs.MemoryTokenStorage; exports.OAuthProvider = _chunkDZYT6QAHcjs.OAuthProvider; exports.OAuthProxy = _chunkDZYT6QAHcjs.OAuthProxy; exports.OAuthProxyError = _chunkDZYT6QAHcjs.OAuthProxyError; exports.PKCEUtils = _chunkDZYT6QAHcjs.PKCEUtils; exports.getAuthSession = _chunkDZYT6QAHcjs.getAuthSession; exports.requireAll = _chunkDZYT6QAHcjs.requireAll; exports.requireAny = _chunkDZYT6QAHcjs.requireAny; exports.requireAuth = _chunkDZYT6QAHcjs.requireAuth; exports.requireRole = _chunkDZYT6QAHcjs.requireRole; exports.requireScopes = _chunkDZYT6QAHcjs.requireScopes;
55
55
  //# sourceMappingURL=index.cjs.map
@@ -1,5 +1,5 @@
1
- import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-vyjR-9Z7.cjs';
2
- export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-vyjR-9Z7.cjs';
1
+ import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-BNqoBTYA.cjs';
2
+ export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-BNqoBTYA.cjs';
3
3
  import 'node:http';
4
4
 
5
5
  /**
@@ -101,6 +101,15 @@ declare class DiskStore implements TokenStorage {
101
101
  * Get the number of stored items
102
102
  */
103
103
  size(): Promise<number>;
104
+ /**
105
+ * Atomically retrieve a value and delete it.
106
+ *
107
+ * rename() is atomic on POSIX filesystems, so when several processes race
108
+ * for the same key exactly one rename succeeds and the losers see ENOENT.
109
+ * That is what makes single-use authorization codes safe when more than one
110
+ * process shares the directory.
111
+ */
112
+ take(key: string): Promise<null | unknown>;
104
113
  /**
105
114
  * Ensure storage directory exists
106
115
  */
@@ -376,7 +385,13 @@ declare class EncryptedTokenStorage implements TokenStorage {
376
385
  delete(key: string): Promise<void>;
377
386
  get(key: string): Promise<null | unknown>;
378
387
  save(key: string, value: unknown, ttl?: number): Promise<void>;
388
+ /**
389
+ * Delegates to the backend so that the atomicity of the underlying store is
390
+ * preserved; falls back to get + delete when the backend cannot do better.
391
+ */
392
+ take(key: string): Promise<null | unknown>;
379
393
  private decrypt;
394
+ private decryptStored;
380
395
  private encrypt;
381
396
  }
382
397
  /**
@@ -398,6 +413,11 @@ declare class MemoryTokenStorage implements TokenStorage {
398
413
  * Get the number of stored items
399
414
  */
400
415
  size(): number;
416
+ /**
417
+ * Atomic by construction: the read and the delete happen in a single
418
+ * synchronous block, so no other task can observe the value in between.
419
+ */
420
+ take(key: string): Promise<null | unknown>;
401
421
  }
402
422
 
403
423
  export { ConsentData, ConsentManager, DiskStore, EncryptedTokenStorage, type JWKSVerificationResult, JWKSVerifier, type JWKSVerifierConfig, type JWTClaims, JWTIssuer, MemoryTokenStorage, OAuthTransaction, PKCEPair, PKCEUtils, TokenStorage, TokenVerificationResult, TokenVerifier };
@@ -1,5 +1,5 @@
1
- import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-vyjR-9Z7.js';
2
- export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-vyjR-9Z7.js';
1
+ import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-BNqoBTYA.js';
2
+ export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-BNqoBTYA.js';
3
3
  import 'node:http';
4
4
 
5
5
  /**
@@ -101,6 +101,15 @@ declare class DiskStore implements TokenStorage {
101
101
  * Get the number of stored items
102
102
  */
103
103
  size(): Promise<number>;
104
+ /**
105
+ * Atomically retrieve a value and delete it.
106
+ *
107
+ * rename() is atomic on POSIX filesystems, so when several processes race
108
+ * for the same key exactly one rename succeeds and the losers see ENOENT.
109
+ * That is what makes single-use authorization codes safe when more than one
110
+ * process shares the directory.
111
+ */
112
+ take(key: string): Promise<null | unknown>;
104
113
  /**
105
114
  * Ensure storage directory exists
106
115
  */
@@ -376,7 +385,13 @@ declare class EncryptedTokenStorage implements TokenStorage {
376
385
  delete(key: string): Promise<void>;
377
386
  get(key: string): Promise<null | unknown>;
378
387
  save(key: string, value: unknown, ttl?: number): Promise<void>;
388
+ /**
389
+ * Delegates to the backend so that the atomicity of the underlying store is
390
+ * preserved; falls back to get + delete when the backend cannot do better.
391
+ */
392
+ take(key: string): Promise<null | unknown>;
379
393
  private decrypt;
394
+ private decryptStored;
380
395
  private encrypt;
381
396
  }
382
397
  /**
@@ -398,6 +413,11 @@ declare class MemoryTokenStorage implements TokenStorage {
398
413
  * Get the number of stored items
399
414
  */
400
415
  size(): number;
416
+ /**
417
+ * Atomic by construction: the read and the delete happen in a single
418
+ * synchronous block, so no other task can observe the value in between.
419
+ */
420
+ take(key: string): Promise<null | unknown>;
401
421
  }
402
422
 
403
423
  export { ConsentData, ConsentManager, DiskStore, EncryptedTokenStorage, type JWKSVerificationResult, JWKSVerifier, type JWKSVerifierConfig, type JWTClaims, JWTIssuer, MemoryTokenStorage, OAuthTransaction, PKCEPair, PKCEUtils, TokenStorage, TokenVerificationResult, TokenVerifier };
@@ -24,7 +24,7 @@ import {
24
24
  requireAuth,
25
25
  requireRole,
26
26
  requireScopes
27
- } from "../chunk-OJG4XYXA.js";
27
+ } from "../chunk-GM44BOI7.js";
28
28
  export {
29
29
  AuthProvider,
30
30
  AzureProvider,