auth.d.ts 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. import { OAuthClientMetadata, OAuthClientInformationMixed, OAuthTokens, OAuthMetadata, OAuthClientInformationFull, OAuthProtectedResourceMetadata, AuthorizationServerMetadata } from '../shared/auth.js';
  2. import { OAuthError } from '../server/auth/errors.js';
  3. import { FetchLike } from '../shared/transport.js';
  4. /**
  5. * Function type for adding client authentication to token requests.
  6. */
  7. export type AddClientAuthentication = (headers: Headers, params: URLSearchParams, url: string | URL, metadata?: AuthorizationServerMetadata) => void | Promise<void>;
  8. /**
  9. * Implements an end-to-end OAuth client to be used with one MCP server.
  10. *
  11. * This client relies upon a concept of an authorized "session," the exact
  12. * meaning of which is application-defined. Tokens, authorization codes, and
  13. * code verifiers should not cross different sessions.
  14. */
  15. export interface OAuthClientProvider {
  16. /**
  17. * The URL to redirect the user agent to after authorization.
  18. * Return undefined for non-interactive flows that don't require user interaction
  19. * (e.g., client_credentials, jwt-bearer).
  20. */
  21. get redirectUrl(): string | URL | undefined;
  22. /**
  23. * External URL the server should use to fetch client metadata document
  24. */
  25. clientMetadataUrl?: string;
  26. /**
  27. * Metadata about this OAuth client.
  28. */
  29. get clientMetadata(): OAuthClientMetadata;
  30. /**
  31. * Returns a OAuth2 state parameter.
  32. */
  33. state?(): string | Promise<string>;
  34. /**
  35. * Loads information about this OAuth client, as registered already with the
  36. * server, or returns `undefined` if the client is not registered with the
  37. * server.
  38. */
  39. clientInformation(): OAuthClientInformationMixed | undefined | Promise<OAuthClientInformationMixed | undefined>;
  40. /**
  41. * If implemented, this permits the OAuth client to dynamically register with
  42. * the server. Client information saved this way should later be read via
  43. * `clientInformation()`.
  44. *
  45. * This method is not required to be implemented if client information is
  46. * statically known (e.g., pre-registered).
  47. */
  48. saveClientInformation?(clientInformation: OAuthClientInformationMixed): void | Promise<void>;
  49. /**
  50. * Loads any existing OAuth tokens for the current session, or returns
  51. * `undefined` if there are no saved tokens.
  52. */
  53. tokens(): OAuthTokens | undefined | Promise<OAuthTokens | undefined>;
  54. /**
  55. * Stores new OAuth tokens for the current session, after a successful
  56. * authorization.
  57. */
  58. saveTokens(tokens: OAuthTokens): void | Promise<void>;
  59. /**
  60. * Invoked to redirect the user agent to the given URL to begin the authorization flow.
  61. */
  62. redirectToAuthorization(authorizationUrl: URL): void | Promise<void>;
  63. /**
  64. * Saves a PKCE code verifier for the current session, before redirecting to
  65. * the authorization flow.
  66. */
  67. saveCodeVerifier(codeVerifier: string): void | Promise<void>;
  68. /**
  69. * Loads the PKCE code verifier for the current session, necessary to validate
  70. * the authorization result.
  71. */
  72. codeVerifier(): string | Promise<string>;
  73. /**
  74. * Adds custom client authentication to OAuth token requests.
  75. *
  76. * This optional method allows implementations to customize how client credentials
  77. * are included in token exchange and refresh requests. When provided, this method
  78. * is called instead of the default authentication logic, giving full control over
  79. * the authentication mechanism.
  80. *
  81. * Common use cases include:
  82. * - Supporting authentication methods beyond the standard OAuth 2.0 methods
  83. * - Adding custom headers for proprietary authentication schemes
  84. * - Implementing client assertion-based authentication (e.g., JWT bearer tokens)
  85. *
  86. * @param headers - The request headers (can be modified to add authentication)
  87. * @param params - The request body parameters (can be modified to add credentials)
  88. * @param url - The token endpoint URL being called
  89. * @param metadata - Optional OAuth metadata for the server, which may include supported authentication methods
  90. */
  91. addClientAuthentication?: AddClientAuthentication;
  92. /**
  93. * If defined, overrides the selection and validation of the
  94. * RFC 8707 Resource Indicator. If left undefined, default
  95. * validation behavior will be used.
  96. *
  97. * Implementations must verify the returned resource matches the MCP server.
  98. */
  99. validateResourceURL?(serverUrl: string | URL, resource?: string): Promise<URL | undefined>;
  100. /**
  101. * If implemented, provides a way for the client to invalidate (e.g. delete) the specified
  102. * credentials, in the case where the server has indicated that they are no longer valid.
  103. * This avoids requiring the user to intervene manually.
  104. */
  105. invalidateCredentials?(scope: 'all' | 'client' | 'tokens' | 'verifier' | 'discovery'): void | Promise<void>;
  106. /**
  107. * Prepares grant-specific parameters for a token request.
  108. *
  109. * This optional method allows providers to customize the token request based on
  110. * the grant type they support. When implemented, it returns the grant type and
  111. * any grant-specific parameters needed for the token exchange.
  112. *
  113. * If not implemented, the default behavior depends on the flow:
  114. * - For authorization code flow: uses code, code_verifier, and redirect_uri
  115. * - For client_credentials: detected via grant_types in clientMetadata
  116. *
  117. * @param scope - Optional scope to request
  118. * @returns Grant type and parameters, or undefined to use default behavior
  119. *
  120. * @example
  121. * // For client_credentials grant:
  122. * prepareTokenRequest(scope) {
  123. * return {
  124. * grantType: 'client_credentials',
  125. * params: scope ? { scope } : {}
  126. * };
  127. * }
  128. *
  129. * @example
  130. * // For authorization_code grant (default behavior):
  131. * async prepareTokenRequest() {
  132. * return {
  133. * grantType: 'authorization_code',
  134. * params: {
  135. * code: this.authorizationCode,
  136. * code_verifier: await this.codeVerifier(),
  137. * redirect_uri: String(this.redirectUrl)
  138. * }
  139. * };
  140. * }
  141. */
  142. prepareTokenRequest?(scope?: string): URLSearchParams | Promise<URLSearchParams | undefined> | undefined;
  143. /**
  144. * Saves the OAuth discovery state after RFC 9728 and authorization server metadata
  145. * discovery. Providers can persist this state to avoid redundant discovery requests
  146. * on subsequent {@linkcode auth} calls.
  147. *
  148. * This state can also be provided out-of-band (e.g., from a previous session or
  149. * external configuration) to bootstrap the OAuth flow without discovery.
  150. *
  151. * Called by {@linkcode auth} after successful discovery.
  152. */
  153. saveDiscoveryState?(state: OAuthDiscoveryState): void | Promise<void>;
  154. /**
  155. * Returns previously saved discovery state, or `undefined` if none is cached.
  156. *
  157. * When available, {@linkcode auth} restores the discovery state (authorization server
  158. * URL, resource metadata, etc.) instead of performing RFC 9728 discovery, reducing
  159. * latency on subsequent calls.
  160. *
  161. * Providers should clear cached discovery state on repeated authentication failures
  162. * (via {@linkcode invalidateCredentials} with scope `'discovery'` or `'all'`) to allow
  163. * re-discovery in case the authorization server has changed.
  164. */
  165. discoveryState?(): OAuthDiscoveryState | undefined | Promise<OAuthDiscoveryState | undefined>;
  166. }
  167. /**
  168. * Discovery state that can be persisted across sessions by an {@linkcode OAuthClientProvider}.
  169. *
  170. * Contains the results of RFC 9728 protected resource metadata discovery and
  171. * authorization server metadata discovery. Persisting this state avoids
  172. * redundant discovery HTTP requests on subsequent {@linkcode auth} calls.
  173. */
  174. export interface OAuthDiscoveryState extends OAuthServerInfo {
  175. /** The URL at which the protected resource metadata was found, if available. */
  176. resourceMetadataUrl?: string;
  177. }
  178. export type AuthResult = 'AUTHORIZED' | 'REDIRECT';
  179. export declare class UnauthorizedError extends Error {
  180. constructor(message?: string);
  181. }
  182. type ClientAuthMethod = 'client_secret_basic' | 'client_secret_post' | 'none';
  183. /**
  184. * Determines the best client authentication method to use based on server support and client configuration.
  185. *
  186. * Priority order (highest to lowest):
  187. * 1. client_secret_basic (if client secret is available)
  188. * 2. client_secret_post (if client secret is available)
  189. * 3. none (for public clients)
  190. *
  191. * @param clientInformation - OAuth client information containing credentials
  192. * @param supportedMethods - Authentication methods supported by the authorization server
  193. * @returns The selected authentication method
  194. */
  195. export declare function selectClientAuthMethod(clientInformation: OAuthClientInformationMixed, supportedMethods: string[]): ClientAuthMethod;
  196. /**
  197. * Parses an OAuth error response from a string or Response object.
  198. *
  199. * If the input is a standard OAuth2.0 error response, it will be parsed according to the spec
  200. * and an instance of the appropriate OAuthError subclass will be returned.
  201. * If parsing fails, it falls back to a generic ServerError that includes
  202. * the response status (if available) and original content.
  203. *
  204. * @param input - A Response object or string containing the error response
  205. * @returns A Promise that resolves to an OAuthError instance
  206. */
  207. export declare function parseErrorResponse(input: Response | string): Promise<OAuthError>;
  208. /**
  209. * Orchestrates the full auth flow with a server.
  210. *
  211. * This can be used as a single entry point for all authorization functionality,
  212. * instead of linking together the other lower-level functions in this module.
  213. */
  214. export declare function auth(provider: OAuthClientProvider, options: {
  215. serverUrl: string | URL;
  216. authorizationCode?: string;
  217. scope?: string;
  218. resourceMetadataUrl?: URL;
  219. fetchFn?: FetchLike;
  220. }): Promise<AuthResult>;
  221. /**
  222. * SEP-991: URL-based Client IDs
  223. * Validate that the client_id is a valid URL with https scheme
  224. */
  225. export declare function isHttpsUrl(value?: string): boolean;
  226. export declare function selectResourceURL(serverUrl: string | URL, provider: OAuthClientProvider, resourceMetadata?: OAuthProtectedResourceMetadata): Promise<URL | undefined>;
  227. /**
  228. * Extract resource_metadata, scope, and error from WWW-Authenticate header.
  229. */
  230. export declare function extractWWWAuthenticateParams(res: Response): {
  231. resourceMetadataUrl?: URL;
  232. scope?: string;
  233. error?: string;
  234. };
  235. /**
  236. * Extract resource_metadata from response header.
  237. * @deprecated Use `extractWWWAuthenticateParams` instead.
  238. */
  239. export declare function extractResourceMetadataUrl(res: Response): URL | undefined;
  240. /**
  241. * Looks up RFC 9728 OAuth 2.0 Protected Resource Metadata.
  242. *
  243. * If the server returns a 404 for the well-known endpoint, this function will
  244. * return `undefined`. Any other errors will be thrown as exceptions.
  245. */
  246. export declare function discoverOAuthProtectedResourceMetadata(serverUrl: string | URL, opts?: {
  247. protocolVersion?: string;
  248. resourceMetadataUrl?: string | URL;
  249. }, fetchFn?: FetchLike): Promise<OAuthProtectedResourceMetadata>;
  250. /**
  251. * Looks up RFC 8414 OAuth 2.0 Authorization Server Metadata.
  252. *
  253. * If the server returns a 404 for the well-known endpoint, this function will
  254. * return `undefined`. Any other errors will be thrown as exceptions.
  255. *
  256. * @deprecated This function is deprecated in favor of `discoverAuthorizationServerMetadata`.
  257. */
  258. export declare function discoverOAuthMetadata(issuer: string | URL, { authorizationServerUrl, protocolVersion }?: {
  259. authorizationServerUrl?: string | URL;
  260. protocolVersion?: string;
  261. }, fetchFn?: FetchLike): Promise<OAuthMetadata | undefined>;
  262. /**
  263. * Builds a list of discovery URLs to try for authorization server metadata.
  264. * URLs are returned in priority order:
  265. * 1. OAuth metadata at the given URL
  266. * 2. OIDC metadata endpoints at the given URL
  267. */
  268. export declare function buildDiscoveryUrls(authorizationServerUrl: string | URL): {
  269. url: URL;
  270. type: 'oauth' | 'oidc';
  271. }[];
  272. /**
  273. * Discovers authorization server metadata with support for RFC 8414 OAuth 2.0 Authorization Server Metadata
  274. * and OpenID Connect Discovery 1.0 specifications.
  275. *
  276. * This function implements a fallback strategy for authorization server discovery:
  277. * 1. Attempts RFC 8414 OAuth metadata discovery first
  278. * 2. If OAuth discovery fails, falls back to OpenID Connect Discovery
  279. *
  280. * @param authorizationServerUrl - The authorization server URL obtained from the MCP Server's
  281. * protected resource metadata, or the MCP server's URL if the
  282. * metadata was not found.
  283. * @param options - Configuration options
  284. * @param options.fetchFn - Optional fetch function for making HTTP requests, defaults to global fetch
  285. * @param options.protocolVersion - MCP protocol version to use, defaults to LATEST_PROTOCOL_VERSION
  286. * @returns Promise resolving to authorization server metadata, or undefined if discovery fails
  287. */
  288. export declare function discoverAuthorizationServerMetadata(authorizationServerUrl: string | URL, { fetchFn, protocolVersion }?: {
  289. fetchFn?: FetchLike;
  290. protocolVersion?: string;
  291. }): Promise<AuthorizationServerMetadata | undefined>;
  292. /**
  293. * Result of {@linkcode discoverOAuthServerInfo}.
  294. */
  295. export interface OAuthServerInfo {
  296. /**
  297. * The authorization server URL, either discovered via RFC 9728
  298. * or derived from the MCP server URL as a fallback.
  299. */
  300. authorizationServerUrl: string;
  301. /**
  302. * The authorization server metadata (endpoints, capabilities),
  303. * or `undefined` if metadata discovery failed.
  304. */
  305. authorizationServerMetadata?: AuthorizationServerMetadata;
  306. /**
  307. * The OAuth 2.0 Protected Resource Metadata from RFC 9728,
  308. * or `undefined` if the server does not support it.
  309. */
  310. resourceMetadata?: OAuthProtectedResourceMetadata;
  311. }
  312. /**
  313. * Discovers the authorization server for an MCP server following
  314. * {@link https://datatracker.ietf.org/doc/html/rfc9728 | RFC 9728} (OAuth 2.0 Protected
  315. * Resource Metadata), with fallback to treating the server URL as the
  316. * authorization server.
  317. *
  318. * This function combines two discovery steps into one call:
  319. * 1. Probes `/.well-known/oauth-protected-resource` on the MCP server to find the
  320. * authorization server URL (RFC 9728).
  321. * 2. Fetches authorization server metadata from that URL (RFC 8414 / OpenID Connect Discovery).
  322. *
  323. * Use this when you need the authorization server metadata for operations outside the
  324. * {@linkcode auth} orchestrator, such as token refresh or token revocation.
  325. *
  326. * @param serverUrl - The MCP resource server URL
  327. * @param opts - Optional configuration
  328. * @param opts.resourceMetadataUrl - Override URL for the protected resource metadata endpoint
  329. * @param opts.fetchFn - Custom fetch function for HTTP requests
  330. * @returns Authorization server URL, metadata, and resource metadata (if available)
  331. */
  332. export declare function discoverOAuthServerInfo(serverUrl: string | URL, opts?: {
  333. resourceMetadataUrl?: URL;
  334. fetchFn?: FetchLike;
  335. }): Promise<OAuthServerInfo>;
  336. /**
  337. * Begins the authorization flow with the given server, by generating a PKCE challenge and constructing the authorization URL.
  338. */
  339. export declare function startAuthorization(authorizationServerUrl: string | URL, { metadata, clientInformation, redirectUrl, scope, state, resource }: {
  340. metadata?: AuthorizationServerMetadata;
  341. clientInformation: OAuthClientInformationMixed;
  342. redirectUrl: string | URL;
  343. scope?: string;
  344. state?: string;
  345. resource?: URL;
  346. }): Promise<{
  347. authorizationUrl: URL;
  348. codeVerifier: string;
  349. }>;
  350. /**
  351. * Prepares token request parameters for an authorization code exchange.
  352. *
  353. * This is the default implementation used by fetchToken when the provider
  354. * doesn't implement prepareTokenRequest.
  355. *
  356. * @param authorizationCode - The authorization code received from the authorization endpoint
  357. * @param codeVerifier - The PKCE code verifier
  358. * @param redirectUri - The redirect URI used in the authorization request
  359. * @returns URLSearchParams for the authorization_code grant
  360. */
  361. export declare function prepareAuthorizationCodeRequest(authorizationCode: string, codeVerifier: string, redirectUri: string | URL): URLSearchParams;
  362. /**
  363. * Exchanges an authorization code for an access token with the given server.
  364. *
  365. * Supports multiple client authentication methods as specified in OAuth 2.1:
  366. * - Automatically selects the best authentication method based on server support
  367. * - Falls back to appropriate defaults when server metadata is unavailable
  368. *
  369. * @param authorizationServerUrl - The authorization server's base URL
  370. * @param options - Configuration object containing client info, auth code, etc.
  371. * @returns Promise resolving to OAuth tokens
  372. * @throws {Error} When token exchange fails or authentication is invalid
  373. */
  374. export declare function exchangeAuthorization(authorizationServerUrl: string | URL, { metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resource, addClientAuthentication, fetchFn }: {
  375. metadata?: AuthorizationServerMetadata;
  376. clientInformation: OAuthClientInformationMixed;
  377. authorizationCode: string;
  378. codeVerifier: string;
  379. redirectUri: string | URL;
  380. resource?: URL;
  381. addClientAuthentication?: OAuthClientProvider['addClientAuthentication'];
  382. fetchFn?: FetchLike;
  383. }): Promise<OAuthTokens>;
  384. /**
  385. * Exchange a refresh token for an updated access token.
  386. *
  387. * Supports multiple client authentication methods as specified in OAuth 2.1:
  388. * - Automatically selects the best authentication method based on server support
  389. * - Preserves the original refresh token if a new one is not returned
  390. *
  391. * @param authorizationServerUrl - The authorization server's base URL
  392. * @param options - Configuration object containing client info, refresh token, etc.
  393. * @returns Promise resolving to OAuth tokens (preserves original refresh_token if not replaced)
  394. * @throws {Error} When token refresh fails or authentication is invalid
  395. */
  396. export declare function refreshAuthorization(authorizationServerUrl: string | URL, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }: {
  397. metadata?: AuthorizationServerMetadata;
  398. clientInformation: OAuthClientInformationMixed;
  399. refreshToken: string;
  400. resource?: URL;
  401. addClientAuthentication?: OAuthClientProvider['addClientAuthentication'];
  402. fetchFn?: FetchLike;
  403. }): Promise<OAuthTokens>;
  404. /**
  405. * Unified token fetching that works with any grant type via provider.prepareTokenRequest().
  406. *
  407. * This function provides a single entry point for obtaining tokens regardless of the
  408. * OAuth grant type. The provider's prepareTokenRequest() method determines which grant
  409. * to use and supplies the grant-specific parameters.
  410. *
  411. * @param provider - OAuth client provider that implements prepareTokenRequest()
  412. * @param authorizationServerUrl - The authorization server's base URL
  413. * @param options - Configuration for the token request
  414. * @returns Promise resolving to OAuth tokens
  415. * @throws {Error} When provider doesn't implement prepareTokenRequest or token fetch fails
  416. *
  417. * @example
  418. * // Provider for client_credentials:
  419. * class MyProvider implements OAuthClientProvider {
  420. * prepareTokenRequest(scope) {
  421. * const params = new URLSearchParams({ grant_type: 'client_credentials' });
  422. * if (scope) params.set('scope', scope);
  423. * return params;
  424. * }
  425. * // ... other methods
  426. * }
  427. *
  428. * const tokens = await fetchToken(provider, authServerUrl, { metadata });
  429. */
  430. export declare function fetchToken(provider: OAuthClientProvider, authorizationServerUrl: string | URL, { metadata, resource, authorizationCode, fetchFn }?: {
  431. metadata?: AuthorizationServerMetadata;
  432. resource?: URL;
  433. /** Authorization code for the default authorization_code grant flow */
  434. authorizationCode?: string;
  435. fetchFn?: FetchLike;
  436. }): Promise<OAuthTokens>;
  437. /**
  438. * Performs OAuth 2.0 Dynamic Client Registration according to RFC 7591.
  439. *
  440. * If `scope` is provided, it overrides `clientMetadata.scope` in the registration
  441. * request body. This allows callers to apply the Scope Selection Strategy (SEP-835)
  442. * consistently across both DCR and the subsequent authorization request.
  443. */
  444. export declare function registerClient(authorizationServerUrl: string | URL, { metadata, clientMetadata, scope, fetchFn }: {
  445. metadata?: AuthorizationServerMetadata;
  446. clientMetadata: OAuthClientMetadata;
  447. scope?: string;
  448. fetchFn?: FetchLike;
  449. }): Promise<OAuthClientInformationFull>;
  450. export {};
  451. //# sourceMappingURL=auth.d.ts.map