|
1 | | -import type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthClientProvider, OAuthTokens } from '@modelcontextprotocol/client'; |
| 1 | +import type { |
| 2 | + OAuthClientInformationMixed, |
| 3 | + OAuthClientMetadata, |
| 4 | + OAuthClientProvider, |
| 5 | + OAuthDiscoveryState, |
| 6 | + OAuthTokens |
| 7 | +} from '@modelcontextprotocol/client'; |
2 | 8 | import { validateClientMetadataUrl } from '@modelcontextprotocol/client'; |
3 | 9 |
|
4 | 10 | /** |
5 | | - * In-memory OAuth client provider for demonstration purposes |
6 | | - * In production, you should persist tokens securely |
| 11 | + * In-memory OAuth client provider for demonstration purposes. |
| 12 | + * In production, you should persist tokens and client credentials securely. |
| 13 | + * |
| 14 | + * Tokens and client credentials are stored as single-slot blobs. The SDK stamps an |
| 15 | + * `issuer` field onto every value it saves; round-tripping the blob unchanged means |
| 16 | + * a credential issued by one authorization server is never reused at another (the |
| 17 | + * SDK reads the stamp back as a key-not-found and re-registers / re-authorizes). |
| 18 | + * To hold credentials for several authorization servers at once, key your storage |
| 19 | + * on the `ctx.issuer` argument instead. |
7 | 20 | */ |
8 | 21 | export class InMemoryOAuthClientProvider implements OAuthClientProvider { |
9 | 22 | private _clientInformation?: OAuthClientInformationMixed; |
10 | 23 | private _tokens?: OAuthTokens; |
11 | 24 | private _codeVerifier?: string; |
| 25 | + private _discoveryState?: OAuthDiscoveryState; |
12 | 26 |
|
13 | 27 | constructor( |
14 | 28 | private readonly _redirectUrl: string | URL, |
@@ -66,4 +80,19 @@ export class InMemoryOAuthClientProvider implements OAuthClientProvider { |
66 | 80 | } |
67 | 81 | return this._codeVerifier; |
68 | 82 | } |
| 83 | + |
| 84 | + saveDiscoveryState(state: OAuthDiscoveryState): void { |
| 85 | + this._discoveryState = state; |
| 86 | + } |
| 87 | + |
| 88 | + discoveryState(): OAuthDiscoveryState | undefined { |
| 89 | + return this._discoveryState; |
| 90 | + } |
| 91 | + |
| 92 | + invalidateCredentials(scope: 'all' | 'client' | 'tokens' | 'verifier' | 'discovery'): void { |
| 93 | + if (scope === 'all' || scope === 'client') this._clientInformation = undefined; |
| 94 | + if (scope === 'all' || scope === 'tokens') this._tokens = undefined; |
| 95 | + if (scope === 'all' || scope === 'verifier') this._codeVerifier = undefined; |
| 96 | + if (scope === 'all' || scope === 'discovery') this._discoveryState = undefined; |
| 97 | + } |
69 | 98 | } |
0 commit comments