fastmcp 4.12.5 → 4.12.6

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/FastMCP.cjs CHANGED
@@ -24,7 +24,7 @@ var _chunkU36NARZGcjs = require('./chunk-U36NARZG.cjs');
24
24
 
25
25
 
26
26
 
27
- var _chunkENMHHQJFcjs = require('./chunk-ENMHHQJF.cjs');
27
+ var _chunkRQ6222DUcjs = require('./chunk-RQ6222DU.cjs');
28
28
 
29
29
 
30
30
 
@@ -49,5 +49,5 @@ var _chunkENMHHQJFcjs = require('./chunk-ENMHHQJF.cjs');
49
49
 
50
50
 
51
51
 
52
- exports.AuthProvider = _chunkENMHHQJFcjs.AuthProvider; exports.AzureProvider = _chunkENMHHQJFcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkU36NARZGcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkU36NARZGcjs.FastMCP; exports.FastMCPError = _chunkU36NARZGcjs.FastMCPError; exports.FastMCPSession = _chunkU36NARZGcjs.FastMCPSession; exports.GitHubProvider = _chunkENMHHQJFcjs.GitHubProvider; exports.GoogleProvider = _chunkENMHHQJFcjs.GoogleProvider; exports.MEDIA_FETCH_TIMEOUT_MS = _chunkU36NARZGcjs.MEDIA_FETCH_TIMEOUT_MS; exports.OAuthProvider = _chunkENMHHQJFcjs.OAuthProvider; exports.ServerState = _chunkU36NARZGcjs.ServerState; exports.SessionError = _chunkU36NARZGcjs.SessionError; exports.UnexpectedStateError = _chunkU36NARZGcjs.UnexpectedStateError; exports.UserError = _chunkU36NARZGcjs.UserError; exports.audioContent = _chunkU36NARZGcjs.audioContent; exports.getAuthSession = _chunkENMHHQJFcjs.getAuthSession; exports.imageContent = _chunkU36NARZGcjs.imageContent; exports.jsonSchemaAdapter = _chunkU36NARZGcjs.jsonSchemaAdapter; exports.requireAll = _chunkENMHHQJFcjs.requireAll; exports.requireAny = _chunkENMHHQJFcjs.requireAny; exports.requireAuth = _chunkENMHHQJFcjs.requireAuth; exports.requireRole = _chunkENMHHQJFcjs.requireRole; exports.requireScopes = _chunkENMHHQJFcjs.requireScopes;
52
+ exports.AuthProvider = _chunkRQ6222DUcjs.AuthProvider; exports.AzureProvider = _chunkRQ6222DUcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkU36NARZGcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkU36NARZGcjs.FastMCP; exports.FastMCPError = _chunkU36NARZGcjs.FastMCPError; exports.FastMCPSession = _chunkU36NARZGcjs.FastMCPSession; exports.GitHubProvider = _chunkRQ6222DUcjs.GitHubProvider; exports.GoogleProvider = _chunkRQ6222DUcjs.GoogleProvider; exports.MEDIA_FETCH_TIMEOUT_MS = _chunkU36NARZGcjs.MEDIA_FETCH_TIMEOUT_MS; exports.OAuthProvider = _chunkRQ6222DUcjs.OAuthProvider; exports.ServerState = _chunkU36NARZGcjs.ServerState; exports.SessionError = _chunkU36NARZGcjs.SessionError; exports.UnexpectedStateError = _chunkU36NARZGcjs.UnexpectedStateError; exports.UserError = _chunkU36NARZGcjs.UserError; exports.audioContent = _chunkU36NARZGcjs.audioContent; exports.getAuthSession = _chunkRQ6222DUcjs.getAuthSession; exports.imageContent = _chunkU36NARZGcjs.imageContent; exports.jsonSchemaAdapter = _chunkU36NARZGcjs.jsonSchemaAdapter; exports.requireAll = _chunkRQ6222DUcjs.requireAll; exports.requireAny = _chunkRQ6222DUcjs.requireAny; exports.requireAuth = _chunkRQ6222DUcjs.requireAuth; exports.requireRole = _chunkRQ6222DUcjs.requireRole; exports.requireScopes = _chunkRQ6222DUcjs.requireScopes;
53
53
  //# 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-B_E71LUD.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-B_E71LUD.cjs';
15
+ import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-B_OJFNC0.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-B_OJFNC0.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-B_E71LUD.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-B_E71LUD.js';
15
+ import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-B_OJFNC0.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-B_OJFNC0.js';
17
17
  import 'node:http';
18
18
 
19
19
  declare class DiscoveryDocumentCache {
package/dist/FastMCP.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  requireAuth,
25
25
  requireRole,
26
26
  requireScopes
27
- } from "./chunk-2ZFQSPXZ.js";
27
+ } from "./chunk-SZ4XCW5X.js";
28
28
  export {
29
29
  AuthProvider,
30
30
  AzureProvider,
@@ -388,11 +388,14 @@ interface TokenStorage {
388
388
  * Atomically retrieve a value and delete it, returning `null` if the key was
389
389
  * absent. At most one caller may observe a given value.
390
390
  *
391
- * Optional, but **required for correctness when more than one process shares
392
- * this storage**: the OAuth proxy consumes authorization codes and
393
- * transactions through it, and single-use enforcement depends on the
394
- * atomicity. Without it the proxy falls back to a non-atomic get + delete,
395
- * where two concurrent requests can both redeem the same authorization code.
391
+ * Optional, but **required for correctness whenever concurrent requests can
392
+ * reach the same record** — which includes a single process, since the check
393
+ * and the delete straddle an await. The OAuth proxy consumes authorization
394
+ * codes, transactions and refresh-token mappings through it, and single-use
395
+ * enforcement depends on the atomicity. Without it the proxy falls back to a
396
+ * non-atomic get + delete, where two concurrent requests can both redeem the
397
+ * same authorization code, or both redeem the same refresh token and walk
398
+ * away with two independent token chains.
396
399
  *
397
400
  * Most backends expose a suitable primitive: Redis `GETDEL`, DynamoDB
398
401
  * `DeleteItem` with `ReturnValues: "ALL_OLD"`, or SQL
@@ -604,10 +607,27 @@ declare class OAuthProxy {
604
607
  * Refresh upstream tokens with provider
605
608
  */
606
609
  private refreshUpstreamTokens;
610
+ /**
611
+ * Put a claimed refresh-token mapping back after a rotation failed, keeping
612
+ * whatever lifetime it had left.
613
+ *
614
+ * A mapping that is already expired, or that carries no usable expiry, is
615
+ * dropped instead. Inventing a TTL here would extend the lifetime of a
616
+ * credential in a security path, and every mapping this proxy writes records
617
+ * `expiresAt`.
618
+ */
619
+ private restoreMapping;
607
620
  /**
608
621
  * Start periodic cleanup of expired transactions and codes
609
622
  */
610
623
  private startCleanup;
624
+ /**
625
+ * Atomically claim a token mapping, mirroring `OAuthProxyStateStore`: at most
626
+ * one caller — across all processes sharing the storage — can receive a given
627
+ * mapping, which is what makes single use enforceable. Falls back to a
628
+ * non-atomic get + delete for storages that do not implement `take`.
629
+ */
630
+ private takeMapping;
611
631
  /**
612
632
  * Validate a redirect URI against the configured allow-list.
613
633
  *
@@ -388,11 +388,14 @@ interface TokenStorage {
388
388
  * Atomically retrieve a value and delete it, returning `null` if the key was
389
389
  * absent. At most one caller may observe a given value.
390
390
  *
391
- * Optional, but **required for correctness when more than one process shares
392
- * this storage**: the OAuth proxy consumes authorization codes and
393
- * transactions through it, and single-use enforcement depends on the
394
- * atomicity. Without it the proxy falls back to a non-atomic get + delete,
395
- * where two concurrent requests can both redeem the same authorization code.
391
+ * Optional, but **required for correctness whenever concurrent requests can
392
+ * reach the same record** — which includes a single process, since the check
393
+ * and the delete straddle an await. The OAuth proxy consumes authorization
394
+ * codes, transactions and refresh-token mappings through it, and single-use
395
+ * enforcement depends on the atomicity. Without it the proxy falls back to a
396
+ * non-atomic get + delete, where two concurrent requests can both redeem the
397
+ * same authorization code, or both redeem the same refresh token and walk
398
+ * away with two independent token chains.
396
399
  *
397
400
  * Most backends expose a suitable primitive: Redis `GETDEL`, DynamoDB
398
401
  * `DeleteItem` with `ReturnValues: "ALL_OLD"`, or SQL
@@ -604,10 +607,27 @@ declare class OAuthProxy {
604
607
  * Refresh upstream tokens with provider
605
608
  */
606
609
  private refreshUpstreamTokens;
610
+ /**
611
+ * Put a claimed refresh-token mapping back after a rotation failed, keeping
612
+ * whatever lifetime it had left.
613
+ *
614
+ * A mapping that is already expired, or that carries no usable expiry, is
615
+ * dropped instead. Inventing a TTL here would extend the lifetime of a
616
+ * credential in a security path, and every mapping this proxy writes records
617
+ * `expiresAt`.
618
+ */
619
+ private restoreMapping;
607
620
  /**
608
621
  * Start periodic cleanup of expired transactions and codes
609
622
  */
610
623
  private startCleanup;
624
+ /**
625
+ * Atomically claim a token mapping, mirroring `OAuthProxyStateStore`: at most
626
+ * one caller — across all processes sharing the storage — can receive a given
627
+ * mapping, which is what makes single use enforceable. Falls back to a
628
+ * non-atomic get + delete for storages that do not implement `take`.
629
+ */
630
+ private takeMapping;
611
631
  /**
612
632
  * Validate a redirect URI against the configured allow-list.
613
633
  *
@@ -24,7 +24,7 @@
24
24
 
25
25
 
26
26
 
27
- var _chunkENMHHQJFcjs = require('../chunk-ENMHHQJF.cjs');
27
+ var _chunkRQ6222DUcjs = require('../chunk-RQ6222DU.cjs');
28
28
 
29
29
 
30
30
 
@@ -51,5 +51,5 @@ var _chunkENMHHQJFcjs = require('../chunk-ENMHHQJF.cjs');
51
51
 
52
52
 
53
53
 
54
- exports.AuthProvider = _chunkENMHHQJFcjs.AuthProvider; exports.AzureProvider = _chunkENMHHQJFcjs.AzureProvider; exports.ConsentManager = _chunkENMHHQJFcjs.ConsentManager; exports.DEFAULT_ACCESS_TOKEN_TTL = _chunkENMHHQJFcjs.DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = _chunkENMHHQJFcjs.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_AUTHORIZATION_CODE_TTL = _chunkENMHHQJFcjs.DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_REFRESH_TOKEN_TTL = _chunkENMHHQJFcjs.DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_TRANSACTION_TTL = _chunkENMHHQJFcjs.DEFAULT_TRANSACTION_TTL; exports.DiskStore = _chunkENMHHQJFcjs.DiskStore; exports.EncryptedTokenStorage = _chunkENMHHQJFcjs.EncryptedTokenStorage; exports.GitHubProvider = _chunkENMHHQJFcjs.GitHubProvider; exports.GoogleProvider = _chunkENMHHQJFcjs.GoogleProvider; exports.JWKSVerifier = _chunkENMHHQJFcjs.JWKSVerifier; exports.JWTIssuer = _chunkENMHHQJFcjs.JWTIssuer; exports.MemoryTokenStorage = _chunkENMHHQJFcjs.MemoryTokenStorage; exports.OAuthProvider = _chunkENMHHQJFcjs.OAuthProvider; exports.OAuthProxy = _chunkENMHHQJFcjs.OAuthProxy; exports.OAuthProxyError = _chunkENMHHQJFcjs.OAuthProxyError; exports.PKCEUtils = _chunkENMHHQJFcjs.PKCEUtils; exports.getAuthSession = _chunkENMHHQJFcjs.getAuthSession; exports.requireAll = _chunkENMHHQJFcjs.requireAll; exports.requireAny = _chunkENMHHQJFcjs.requireAny; exports.requireAuth = _chunkENMHHQJFcjs.requireAuth; exports.requireRole = _chunkENMHHQJFcjs.requireRole; exports.requireScopes = _chunkENMHHQJFcjs.requireScopes;
54
+ exports.AuthProvider = _chunkRQ6222DUcjs.AuthProvider; exports.AzureProvider = _chunkRQ6222DUcjs.AzureProvider; exports.ConsentManager = _chunkRQ6222DUcjs.ConsentManager; exports.DEFAULT_ACCESS_TOKEN_TTL = _chunkRQ6222DUcjs.DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = _chunkRQ6222DUcjs.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_AUTHORIZATION_CODE_TTL = _chunkRQ6222DUcjs.DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_REFRESH_TOKEN_TTL = _chunkRQ6222DUcjs.DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_TRANSACTION_TTL = _chunkRQ6222DUcjs.DEFAULT_TRANSACTION_TTL; exports.DiskStore = _chunkRQ6222DUcjs.DiskStore; exports.EncryptedTokenStorage = _chunkRQ6222DUcjs.EncryptedTokenStorage; exports.GitHubProvider = _chunkRQ6222DUcjs.GitHubProvider; exports.GoogleProvider = _chunkRQ6222DUcjs.GoogleProvider; exports.JWKSVerifier = _chunkRQ6222DUcjs.JWKSVerifier; exports.JWTIssuer = _chunkRQ6222DUcjs.JWTIssuer; exports.MemoryTokenStorage = _chunkRQ6222DUcjs.MemoryTokenStorage; exports.OAuthProvider = _chunkRQ6222DUcjs.OAuthProvider; exports.OAuthProxy = _chunkRQ6222DUcjs.OAuthProxy; exports.OAuthProxyError = _chunkRQ6222DUcjs.OAuthProxyError; exports.PKCEUtils = _chunkRQ6222DUcjs.PKCEUtils; exports.getAuthSession = _chunkRQ6222DUcjs.getAuthSession; exports.requireAll = _chunkRQ6222DUcjs.requireAll; exports.requireAny = _chunkRQ6222DUcjs.requireAny; exports.requireAuth = _chunkRQ6222DUcjs.requireAuth; exports.requireRole = _chunkRQ6222DUcjs.requireRole; exports.requireScopes = _chunkRQ6222DUcjs.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-B_E71LUD.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-B_E71LUD.cjs';
1
+ import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-B_OJFNC0.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-B_OJFNC0.cjs';
3
3
  import 'node:http';
4
4
 
5
5
  /**
@@ -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-B_E71LUD.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-B_E71LUD.js';
1
+ import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-B_OJFNC0.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-B_OJFNC0.js';
3
3
  import 'node:http';
4
4
 
5
5
  /**
@@ -24,7 +24,7 @@ import {
24
24
  requireAuth,
25
25
  requireRole,
26
26
  requireScopes
27
- } from "../chunk-2ZFQSPXZ.js";
27
+ } from "../chunk-SZ4XCW5X.js";
28
28
  export {
29
29
  AuthProvider,
30
30
  AzureProvider,
@@ -1802,51 +1802,62 @@ var OAuthProxy = (_class4 = class {
1802
1802
  if (!jti) {
1803
1803
  throw new OAuthProxyError("invalid_grant", "Refresh token missing JTI");
1804
1804
  }
1805
- const mapping = await this.tokenStorage.get(`mapping:${jti}`);
1805
+ const mapping = await this.takeMapping(jti);
1806
1806
  if (!mapping) {
1807
1807
  throw new OAuthProxyError(
1808
1808
  "invalid_grant",
1809
1809
  "Refresh token already used or expired"
1810
1810
  );
1811
1811
  }
1812
- const upstreamTokens = await this.tokenStorage.get(
1813
- `upstream:${mapping.upstreamTokenKey}`
1814
- );
1815
- if (!upstreamTokens) {
1816
- throw new OAuthProxyError(
1817
- "invalid_grant",
1818
- "Upstream tokens not found or expired"
1812
+ try {
1813
+ const upstreamTokens = await this.tokenStorage.get(
1814
+ `upstream:${mapping.upstreamTokenKey}`
1819
1815
  );
1820
- }
1821
- if (!upstreamTokens.refreshToken) {
1822
- throw new OAuthProxyError(
1823
- "invalid_grant",
1824
- "No upstream refresh token available"
1816
+ if (!upstreamTokens) {
1817
+ throw new OAuthProxyError(
1818
+ "invalid_grant",
1819
+ "Upstream tokens not found or expired"
1820
+ );
1821
+ }
1822
+ if (!upstreamTokens.refreshToken) {
1823
+ throw new OAuthProxyError(
1824
+ "invalid_grant",
1825
+ "No upstream refresh token available"
1826
+ );
1827
+ }
1828
+ const refreshedUpstreamTokens = await this.refreshUpstreamTokens(
1829
+ upstreamTokens.refreshToken,
1830
+ request.scope
1825
1831
  );
1832
+ if (refreshedUpstreamTokens.scope.length === 0) {
1833
+ refreshedUpstreamTokens.scope = upstreamTokens.scope;
1834
+ }
1835
+ const refreshTokenTtl = _nullishCoalesce(_nullishCoalesce(refreshedUpstreamTokens.refreshExpiresIn, () => ( this.config.refreshTokenTtl)), () => ( DEFAULT_REFRESH_TOKEN_TTL));
1836
+ const accessTokenTtl = this.calculateAccessTokenTtl(
1837
+ refreshedUpstreamTokens
1838
+ );
1839
+ const upstreamStorageTtl = Math.max(accessTokenTtl, refreshTokenTtl, 1);
1840
+ await this.tokenStorage.save(
1841
+ `upstream:${mapping.upstreamTokenKey}`,
1842
+ refreshedUpstreamTokens,
1843
+ upstreamStorageTtl
1844
+ );
1845
+ return await this.issueSwappedTokensForRefresh(
1846
+ mapping.clientId,
1847
+ refreshedUpstreamTokens,
1848
+ mapping.upstreamTokenKey
1849
+ );
1850
+ } catch (error) {
1851
+ try {
1852
+ await this.restoreMapping(jti, mapping);
1853
+ } catch (restoreError) {
1854
+ console.error(
1855
+ `Failed to restore refresh token mapping ${jti}:`,
1856
+ restoreError
1857
+ );
1858
+ }
1859
+ throw error;
1826
1860
  }
1827
- const refreshedUpstreamTokens = await this.refreshUpstreamTokens(
1828
- upstreamTokens.refreshToken,
1829
- request.scope
1830
- );
1831
- if (refreshedUpstreamTokens.scope.length === 0) {
1832
- refreshedUpstreamTokens.scope = upstreamTokens.scope;
1833
- }
1834
- const refreshTokenTtl = _nullishCoalesce(_nullishCoalesce(refreshedUpstreamTokens.refreshExpiresIn, () => ( this.config.refreshTokenTtl)), () => ( DEFAULT_REFRESH_TOKEN_TTL));
1835
- const accessTokenTtl = this.calculateAccessTokenTtl(
1836
- refreshedUpstreamTokens
1837
- );
1838
- const upstreamStorageTtl = Math.max(accessTokenTtl, refreshTokenTtl, 1);
1839
- await this.tokenStorage.save(
1840
- `upstream:${mapping.upstreamTokenKey}`,
1841
- refreshedUpstreamTokens,
1842
- upstreamStorageTtl
1843
- );
1844
- return await this.issueSwappedTokensForRefresh(
1845
- mapping.clientId,
1846
- refreshedUpstreamTokens,
1847
- mapping.upstreamTokenKey,
1848
- jti
1849
- );
1850
1861
  }
1851
1862
  /**
1852
1863
  * Issue swapped tokens (JWT pattern)
@@ -1927,11 +1938,10 @@ var OAuthProxy = (_class4 = class {
1927
1938
  /**
1928
1939
  * Issue swapped tokens for refresh flow
1929
1940
  */
1930
- async issueSwappedTokensForRefresh(clientId, upstreamTokens, upstreamTokenKey, oldJti) {
1941
+ async issueSwappedTokensForRefresh(clientId, upstreamTokens, upstreamTokenKey) {
1931
1942
  if (!this.jwtIssuer) {
1932
1943
  throw new Error("JWT issuer not initialized");
1933
1944
  }
1934
- await this.tokenStorage.delete(`mapping:${oldJti}`);
1935
1945
  const customClaims = await this.extractUpstreamClaims(upstreamTokens);
1936
1946
  const accessTokenTtl = this.calculateAccessTokenTtl(upstreamTokens);
1937
1947
  const refreshTokenTtl = upstreamTokens.refreshToken ? _nullishCoalesce(_nullishCoalesce(upstreamTokens.refreshExpiresIn, () => ( this.config.refreshTokenTtl)), () => ( DEFAULT_REFRESH_TOKEN_TTL)) : 0;
@@ -2108,6 +2118,29 @@ var OAuthProxy = (_class4 = class {
2108
2118
  tokenType: tokens.token_type || "Bearer"
2109
2119
  };
2110
2120
  }
2121
+ /**
2122
+ * Put a claimed refresh-token mapping back after a rotation failed, keeping
2123
+ * whatever lifetime it had left.
2124
+ *
2125
+ * A mapping that is already expired, or that carries no usable expiry, is
2126
+ * dropped instead. Inventing a TTL here would extend the lifetime of a
2127
+ * credential in a security path, and every mapping this proxy writes records
2128
+ * `expiresAt`.
2129
+ */
2130
+ async restoreMapping(jti, mapping) {
2131
+ if (!mapping.expiresAt) {
2132
+ return;
2133
+ }
2134
+ const expiresAt = new Date(mapping.expiresAt).getTime();
2135
+ if (Number.isNaN(expiresAt)) {
2136
+ return;
2137
+ }
2138
+ const ttl = Math.ceil((expiresAt - Date.now()) / 1e3);
2139
+ if (ttl <= 0) {
2140
+ return;
2141
+ }
2142
+ await this.tokenStorage.save(`mapping:${jti}`, mapping, ttl);
2143
+ }
2111
2144
  /**
2112
2145
  * Start periodic cleanup of expired transactions and codes
2113
2146
  */
@@ -2116,6 +2149,24 @@ var OAuthProxy = (_class4 = class {
2116
2149
  this.cleanup();
2117
2150
  }, 6e4);
2118
2151
  }
2152
+ /**
2153
+ * Atomically claim a token mapping, mirroring `OAuthProxyStateStore`: at most
2154
+ * one caller — across all processes sharing the storage — can receive a given
2155
+ * mapping, which is what makes single use enforceable. Falls back to a
2156
+ * non-atomic get + delete for storages that do not implement `take`.
2157
+ */
2158
+ async takeMapping(jti) {
2159
+ const key = `mapping:${jti}`;
2160
+ if (this.tokenStorage.take) {
2161
+ return await this.tokenStorage.take(key);
2162
+ }
2163
+ const stored = await this.tokenStorage.get(key);
2164
+ if (stored === null) {
2165
+ return null;
2166
+ }
2167
+ await this.tokenStorage.delete(key);
2168
+ return stored;
2169
+ }
2119
2170
  /**
2120
2171
  * Validate a redirect URI against the configured allow-list.
2121
2172
  *
@@ -2733,4 +2784,4 @@ Original error: ${error.message}`
2733
2784
 
2734
2785
 
2735
2786
  exports.getAuthSession = getAuthSession; exports.requireAll = requireAll; exports.requireAny = requireAny; exports.requireAuth = requireAuth; exports.requireRole = requireRole; exports.requireScopes = requireScopes; exports.DEFAULT_ACCESS_TOKEN_TTL = DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_REFRESH_TOKEN_TTL = DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_AUTHORIZATION_CODE_TTL = DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_TRANSACTION_TTL = DEFAULT_TRANSACTION_TTL; exports.ConsentManager = ConsentManager; exports.JWTIssuer = JWTIssuer; exports.PKCEUtils = PKCEUtils; exports.EncryptedTokenStorage = EncryptedTokenStorage; exports.MemoryTokenStorage = MemoryTokenStorage; exports.OAuthProxy = OAuthProxy; exports.OAuthProxyError = OAuthProxyError; exports.AuthProvider = AuthProvider; exports.AzureProvider = AzureProvider; exports.GitHubProvider = GitHubProvider; exports.GoogleProvider = GoogleProvider; exports.OAuthProvider = OAuthProvider; exports.DiskStore = DiskStore; exports.JWKSVerifier = JWKSVerifier;
2736
- //# sourceMappingURL=chunk-ENMHHQJF.cjs.map
2787
+ //# sourceMappingURL=chunk-RQ6222DU.cjs.map