diff --git a/docs/docs.json b/docs/docs.json index fe2891bdc..342c2568f 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -19,12 +19,11 @@ "light": "#4cc9f0", "primary": "#2d00f7" }, - "fonts": { - "heading": { "family": "Google Sans" }, - "body": { "family": "BlinkMacSystemFont" } - }, "contextual": { - "options": ["copy", "view"] + "options": [ + "copy", + "view" + ] }, "description": "The fast, Pythonic way to build MCP servers and clients.", "errors": { @@ -38,6 +37,14 @@ "dark": "/assets/brand/favicon.svg", "light": "/assets/brand/favicon.svg" }, + "fonts": { + "body": { + "family": "BlinkMacSystemFont" + }, + "heading": { + "family": "Google Sans" + } + }, "footer": { "socials": { "discord": "https://discord.gg/uu8dJCgttd", @@ -150,7 +157,10 @@ { "group": "Essentials", "icon": "cube", - "pages": ["clients/client", "clients/transports"] + "pages": [ + "clients/client", + "clients/transports" + ] }, { "group": "Core Operations", @@ -176,7 +186,10 @@ { "group": "Authentication", "icon": "user-shield", - "pages": ["clients/auth/oauth", "clients/auth/bearer"] + "pages": [ + "clients/auth/oauth", + "clients/auth/bearer" + ] } ] }, @@ -230,7 +243,10 @@ { "group": "API Integration", "icon": "globe", - "pages": ["integrations/fastapi", "integrations/openapi"] + "pages": [ + "integrations/fastapi", + "integrations/openapi" + ] } ] }, @@ -336,7 +352,9 @@ "python-sdk/fastmcp-server-auth-__init__", "python-sdk/fastmcp-server-auth-auth", "python-sdk/fastmcp-server-auth-jwt_issuer", + "python-sdk/fastmcp-server-auth-oauth_dcr_proxy", "python-sdk/fastmcp-server-auth-oauth_proxy", + "python-sdk/fastmcp-server-auth-oidc_dcr_proxy", "python-sdk/fastmcp-server-auth-oidc_proxy", { "group": "providers", @@ -461,17 +479,17 @@ "search": { "prompt": "Search the docs..." }, + "styling": { + "codeblocks": { + "theme": { + "dark": "dark-plus", + "light": "snazzy-light" + } + } + }, "theme": "almond", "thumbnails": { "appearance": "light", "background": "/assets/brand/thumbnail-background.png" - }, - "styling": { - "codeblocks": { - "theme": { - "light": "snazzy-light", - "dark": "dark-plus" - } - } } } diff --git a/docs/python-sdk/fastmcp-server-auth-oauth_dcr_proxy.mdx b/docs/python-sdk/fastmcp-server-auth-oauth_dcr_proxy.mdx new file mode 100644 index 000000000..e27c8be0e --- /dev/null +++ b/docs/python-sdk/fastmcp-server-auth-oauth_dcr_proxy.mdx @@ -0,0 +1,404 @@ +--- +title: oauth_dcr_proxy +sidebarTitle: oauth_dcr_proxy +--- + +# `fastmcp.server.auth.oauth_dcr_proxy` + + +OAuth Proxy Provider for FastMCP. + +This provider acts as a transparent proxy to an upstream OAuth Authorization Server, +handling Dynamic Client Registration locally while forwarding all other OAuth flows. +This enables authentication with upstream providers that don't support DCR or have +restricted client registration policies. + +Key features: +- Proxies authorization and token endpoints to upstream server +- Implements local Dynamic Client Registration with fixed upstream credentials +- Validates tokens using upstream JWKS +- Maintains minimal local state for bookkeeping +- Enhanced logging with request correlation + +This implementation is based on the OAuth 2.1 specification and is designed for +production use with enterprise identity providers. + + +## Functions + +### `create_consent_html` + +```python +create_consent_html(client_id: str, redirect_uri: str, scopes: list[str], txn_id: str, csrf_token: str, client_name: str | None = None, title: str = 'Authorization Consent', server_name: str | None = None, server_icon_url: str | None = None, server_website_url: str | None = None) -> str +``` + + +Create a styled HTML consent page for OAuth authorization requests. + + +## Classes + +### `OAuthTransaction` + + +OAuth transaction state for consent flow. + +Stored server-side to track active authorization flows with client context. +Includes CSRF tokens for consent protection per MCP security best practices. + + +### `ClientCode` + + +Client authorization code with PKCE and upstream tokens. + +Stored server-side after upstream IdP callback. Contains the upstream +tokens bound to the client's PKCE challenge for secure token exchange. + + +### `UpstreamTokenSet` + + +Stored upstream OAuth tokens from identity provider. + +These tokens are obtained from the upstream provider (Google, GitHub, etc.) +and are stored encrypted at rest. They are never exposed to MCP clients. + + +### `JTIMapping` + + +Maps FastMCP token JTI to upstream token ID. + +This allows stateless JWT validation while still being able to look up +the corresponding upstream token when tools need to access upstream APIs. + + +### `ProxyDCRClient` + + +Client for DCR proxy with configurable redirect URI validation. + +This special client class is critical for the OAuth proxy to work correctly +with Dynamic Client Registration (DCR). Here's why it exists: + +Problem: +-------- +When MCP clients use OAuth, they dynamically register with random localhost +ports (e.g., http://localhost:55454/callback). The OAuth proxy needs to: +1. Accept these dynamic redirect URIs from clients based on configured patterns +2. Use its own fixed redirect URI with the upstream provider (Google, GitHub, etc.) +3. Forward the authorization code back to the client's dynamic URI + +Solution: +--------- +This class validates redirect URIs against configurable patterns, +while the proxy internally uses its own fixed redirect URI with the upstream +provider. This allows the flow to work even when clients reconnect with +different ports or when tokens are cached. + +Without proper validation, clients could get "Redirect URI not registered" errors +when trying to authenticate with cached tokens, or security vulnerabilities could +arise from accepting arbitrary redirect URIs. + + +**Methods:** + +#### `validate_redirect_uri` + +```python +validate_redirect_uri(self, redirect_uri: AnyUrl | None) -> AnyUrl +``` + +Validate redirect URI against allowed patterns. + +Since we're acting as a proxy and clients register dynamically, +we validate their redirect URIs against configurable patterns. +This is essential for cached token scenarios where the client may +reconnect with a different port. + + +### `TokenHandler` + + +TokenHandler that returns OAuth 2.1 compliant error responses. + +The MCP SDK always returns HTTP 400 for all client authentication issues. +However, OAuth 2.1 Section 5.3 and the MCP specification require that +invalid or expired tokens MUST receive a HTTP 401 response. + +This handler extends the base MCP SDK TokenHandler to transform client +authentication failures into OAuth 2.1 compliant responses: +- Changes 'unauthorized_client' to 'invalid_client' error code +- Returns HTTP 401 status code instead of 400 for client auth failures + +Per OAuth 2.1 Section 5.3: "The authorization server MAY return an HTTP 401 +(Unauthorized) status code to indicate which HTTP authentication schemes +are supported." + +Per MCP spec: "Invalid or expired tokens MUST receive a HTTP 401 response." + + +**Methods:** + +#### `response` + +```python +response(self, obj: TokenSuccessResponse | TokenErrorResponse) +``` + +Override response method to provide OAuth 2.1 compliant error handling. + + +### `OAuthDCRProxy` + + +OAuth provider that presents a DCR-compliant interface while proxying to non-DCR IDPs. + +Purpose +------- +MCP clients expect OAuth providers to support Dynamic Client Registration (DCR), +where clients can register themselves dynamically and receive unique credentials. +Most enterprise IDPs (Google, GitHub, Azure AD, etc.) don't support DCR and require +pre-registered OAuth applications with fixed credentials. + +This proxy bridges that gap by: +- Presenting a full DCR-compliant OAuth interface to MCP clients +- Translating DCR registration requests to use pre-configured upstream credentials +- Proxying all OAuth flows to the upstream IDP with appropriate translations +- Managing the state and security requirements of both protocols + +Architecture Overview +-------------------- +The proxy maintains a single OAuth app registration with the upstream provider +while allowing unlimited MCP clients to register and authenticate dynamically. +It implements the complete OAuth 2.1 + DCR specification for clients while +translating to whatever OAuth variant the upstream provider requires. + +Key Translation Challenges Solved +--------------------------------- +1. Dynamic Client Registration: + - MCP clients expect to register dynamically and get unique credentials + - Upstream IDPs require pre-registered apps with fixed credentials + - Solution: Accept DCR requests, return shared upstream credentials + +2. Dynamic Redirect URIs: + - MCP clients use random localhost ports that change between sessions + - Upstream IDPs require fixed, pre-registered redirect URIs + - Solution: Use proxy's fixed callback URL with upstream, forward to client's dynamic URI + +3. Authorization Code Mapping: + - Upstream returns codes for the proxy's redirect URI + - Clients expect codes for their own redirect URIs + - Solution: Exchange upstream code server-side, issue new code to client + +4. State Parameter Collision: + - Both client and proxy need to maintain state through the flow + - Only one state parameter available in OAuth + - Solution: Use transaction ID as state with upstream, preserve client's state + +5. Token Management: + - Clients may expect different token formats/claims than upstream provides + - Need to track tokens for revocation and refresh + - Solution: Store token relationships, forward upstream tokens transparently + +OAuth Flow Implementation +------------------------ +1. Client Registration (DCR): + - Accept any client registration request + - Store ProxyDCRClient that accepts dynamic redirect URIs + +2. Authorization: + - Store transaction mapping client details to proxy flow + - Redirect to upstream with proxy's fixed redirect URI + - Use transaction ID as state parameter with upstream + +3. Upstream Callback: + - Exchange upstream authorization code for tokens (server-side) + - Generate new authorization code bound to client's PKCE challenge + - Redirect to client's original dynamic redirect URI + +4. Token Exchange: + - Validate client's code and PKCE verifier + - Return previously obtained upstream tokens + - Clean up one-time use authorization code + +5. Token Refresh: + - Forward refresh requests to upstream using authlib + - Handle token rotation if upstream issues new refresh token + - Update local token mappings + +State Management +--------------- +The proxy maintains minimal but crucial state: +- _oauth_transactions: Active authorization flows with client context +- _client_codes: Authorization codes with PKCE challenges and upstream tokens +- _access_tokens, _refresh_tokens: Token storage for revocation +- Token relationship mappings for cleanup and rotation + +Security Considerations +---------------------- +- PKCE enforced end-to-end (client to proxy, proxy to upstream) +- Authorization codes are single-use with short expiry +- Transaction IDs are cryptographically random +- All state is cleaned up after use to prevent replay +- Token validation delegates to upstream provider + +Provider Compatibility +--------------------- +Works with any OAuth 2.0 provider that supports: +- Authorization code flow +- Fixed redirect URI (configured in provider's app settings) +- Standard token endpoint + +Handles provider-specific requirements: +- Google: Ensures minimum scope requirements +- GitHub: Compatible with OAuth Apps and GitHub Apps +- Azure AD: Handles tenant-specific endpoints +- Generic: Works with any spec-compliant provider + + +**Methods:** + +#### `get_client` + +```python +get_client(self, client_id: str) -> OAuthClientInformationFull | None +``` + +Get client information by ID. This is generally the random ID +provided to the DCR client during registration, not the upstream client ID. + +For unregistered clients, returns None (which will raise an error in the SDK). + + +#### `register_client` + +```python +register_client(self, client_info: OAuthClientInformationFull) -> None +``` + +Register a client locally + +When a client registers, we create a ProxyDCRClient that is more +forgiving about validating redirect URIs, since the DCR client's +redirect URI will likely be localhost or unknown to the proxied IDP. The +proxied IDP only knows about this server's fixed redirect URI. + + +#### `authorize` + +```python +authorize(self, client: OAuthClientInformationFull, params: AuthorizationParams) -> str +``` + +Start OAuth transaction and route through consent interstitial. + +Flow: +1. Store transaction with client details and PKCE (if forwarding) +2. Return local /consent URL; browser visits consent first +3. Consent handler redirects to upstream IdP if approved/already approved + + +#### `load_authorization_code` + +```python +load_authorization_code(self, client: OAuthClientInformationFull, authorization_code: str) -> AuthorizationCode | None +``` + +Load authorization code for validation. + +Look up our client code and return authorization code object +with PKCE challenge for validation. + + +#### `exchange_authorization_code` + +```python +exchange_authorization_code(self, client: OAuthClientInformationFull, authorization_code: AuthorizationCode) -> OAuthToken +``` + +Exchange authorization code for FastMCP-issued tokens. + +Implements the token factory pattern: +1. Retrieves upstream tokens from stored authorization code +2. Extracts user identity from upstream token +3. Encrypts and stores upstream tokens +4. Issues FastMCP-signed JWT tokens +5. Returns FastMCP tokens (NOT upstream tokens) + +PKCE validation is handled by the MCP framework before this method is called. + + +#### `load_refresh_token` + +```python +load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str) -> RefreshToken | None +``` + +Load refresh token from local storage. + + +#### `exchange_refresh_token` + +```python +exchange_refresh_token(self, client: OAuthClientInformationFull, refresh_token: RefreshToken, scopes: list[str]) -> OAuthToken +``` + +Exchange FastMCP refresh token for new FastMCP access token. + +Implements two-tier refresh: +1. Verify FastMCP refresh token +2. Look up upstream token via JTI mapping +3. Refresh upstream token with upstream provider +4. Update stored upstream token +5. Issue new FastMCP access token +6. Keep same FastMCP refresh token (unless upstream rotates) + + +#### `load_access_token` + +```python +load_access_token(self, token: str) -> AccessToken | None +``` + +Validate FastMCP JWT by swapping for upstream token. + +This implements the token swap pattern: +1. Verify FastMCP JWT signature (proves it's our token) +2. Look up upstream token via JTI mapping +3. Decrypt upstream token +4. Validate upstream token with provider (GitHub API, JWT validation, etc.) +5. Return upstream validation result + +The FastMCP JWT is a reference token - all authorization data comes +from validating the upstream token via the TokenVerifier. + + +#### `revoke_token` + +```python +revoke_token(self, token: AccessToken | RefreshToken) -> None +``` + +Revoke token locally and with upstream server if supported. + +Removes tokens from local storage and attempts to revoke them with +the upstream server if a revocation endpoint is configured. + + +#### `get_routes` + +```python +get_routes(self, mcp_path: str | None = None) -> list[Route] +``` + +Get OAuth routes with custom proxy token handler. + +This method creates standard OAuth routes and replaces the token endpoint +with our proxy handler that forwards requests to the upstream OAuth server. + +**Args:** +- `mcp_path`: The path where the MCP endpoint is mounted (e.g., "/mcp") +This is used to advertise the resource URL in metadata. + diff --git a/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx b/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx index a2fba81e9..f350959c7 100644 --- a/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx +++ b/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx @@ -3,402 +3,11 @@ title: oauth_proxy sidebarTitle: oauth_proxy --- -# `fastmcp.server.auth.oauth_dcr_proxy` +# `fastmcp.server.auth.oauth_proxy` -OAuth Proxy Provider for FastMCP. +Backwards compatibility shim for oauth_proxy.py -This provider acts as a transparent proxy to an upstream OAuth Authorization Server, -handling Dynamic Client Registration locally while forwarding all other OAuth flows. -This enables authentication with upstream providers that don't support DCR or have -restricted client registration policies. - -Key features: -- Proxies authorization and token endpoints to upstream server -- Implements local Dynamic Client Registration with fixed upstream credentials -- Validates tokens using upstream JWKS -- Maintains minimal local state for bookkeeping -- Enhanced logging with request correlation - -This implementation is based on the OAuth 2.1 specification and is designed for -production use with enterprise identity providers. - - -## Functions - -### `create_consent_html` - -```python -create_consent_html(client_id: str, redirect_uri: str, scopes: list[str], txn_id: str, csrf_token: str, client_name: str | None = None, title: str = 'Authorization Consent', server_name: str | None = None, server_icon_url: str | None = None, server_website_url: str | None = None) -> str -``` - - -Create a styled HTML consent page for OAuth authorization requests. - - -## Classes - -### `OAuthTransaction` - - -OAuth transaction state for consent flow. - -Stored server-side to track active authorization flows with client context. -Includes CSRF tokens for consent protection per MCP security best practices. - - -### `ClientCode` - - -Client authorization code with PKCE and upstream tokens. - -Stored server-side after upstream IdP callback. Contains the upstream -tokens bound to the client's PKCE challenge for secure token exchange. - - -### `UpstreamTokenSet` - - -Stored upstream OAuth tokens from identity provider. - -These tokens are obtained from the upstream provider (Google, GitHub, etc.) -and are stored encrypted at rest. They are never exposed to MCP clients. - - -### `JTIMapping` - - -Maps FastMCP token JTI to upstream token ID. - -This allows stateless JWT validation while still being able to look up -the corresponding upstream token when tools need to access upstream APIs. - - -### `ProxyDCRClient` - - -Client for DCR proxy with configurable redirect URI validation. - -This special client class is critical for the OAuth proxy to work correctly -with Dynamic Client Registration (DCR). Here's why it exists: - -Problem: --------- -When MCP clients use OAuth, they dynamically register with random localhost -ports (e.g., http://localhost:55454/callback). The OAuth proxy needs to: -1. Accept these dynamic redirect URIs from clients based on configured patterns -2. Use its own fixed redirect URI with the upstream provider (Google, GitHub, etc.) -3. Forward the authorization code back to the client's dynamic URI - -Solution: ---------- -This class validates redirect URIs against configurable patterns, -while the proxy internally uses its own fixed redirect URI with the upstream -provider. This allows the flow to work even when clients reconnect with -different ports or when tokens are cached. - -Without proper validation, clients could get "Redirect URI not registered" errors -when trying to authenticate with cached tokens, or security vulnerabilities could -arise from accepting arbitrary redirect URIs. - - -**Methods:** - -#### `validate_redirect_uri` - -```python -validate_redirect_uri(self, redirect_uri: AnyUrl | None) -> AnyUrl -``` - -Validate redirect URI against allowed patterns. - -Since we're acting as a proxy and clients register dynamically, -we validate their redirect URIs against configurable patterns. -This is essential for cached token scenarios where the client may -reconnect with a different port. - - -### `TokenHandler` - - -TokenHandler that returns OAuth 2.1 compliant error responses. - -The MCP SDK always returns HTTP 400 for all client authentication issues. -However, OAuth 2.1 Section 5.3 and the MCP specification require that -invalid or expired tokens MUST receive a HTTP 401 response. - -This handler extends the base MCP SDK TokenHandler to transform client -authentication failures into OAuth 2.1 compliant responses: -- Changes 'unauthorized_client' to 'invalid_client' error code -- Returns HTTP 401 status code instead of 400 for client auth failures - -Per OAuth 2.1 Section 5.3: "The authorization server MAY return an HTTP 401 -(Unauthorized) status code to indicate which HTTP authentication schemes -are supported." - -Per MCP spec: "Invalid or expired tokens MUST receive a HTTP 401 response." - - -**Methods:** - -#### `response` - -```python -response(self, obj: TokenSuccessResponse | TokenErrorResponse) -``` - -Override response method to provide OAuth 2.1 compliant error handling. - - -### `OAuthProxy` - - -OAuth provider that presents a DCR-compliant interface while proxying to non-DCR IDPs. - -Purpose -------- -MCP clients expect OAuth providers to support Dynamic Client Registration (DCR), -where clients can register themselves dynamically and receive unique credentials. -Most enterprise IDPs (Google, GitHub, Azure AD, etc.) don't support DCR and require -pre-registered OAuth applications with fixed credentials. - -This proxy bridges that gap by: -- Presenting a full DCR-compliant OAuth interface to MCP clients -- Translating DCR registration requests to use pre-configured upstream credentials -- Proxying all OAuth flows to the upstream IDP with appropriate translations -- Managing the state and security requirements of both protocols - -Architecture Overview --------------------- -The proxy maintains a single OAuth app registration with the upstream provider -while allowing unlimited MCP clients to register and authenticate dynamically. -It implements the complete OAuth 2.1 + DCR specification for clients while -translating to whatever OAuth variant the upstream provider requires. - -Key Translation Challenges Solved ---------------------------------- -1. Dynamic Client Registration: - - MCP clients expect to register dynamically and get unique credentials - - Upstream IDPs require pre-registered apps with fixed credentials - - Solution: Accept DCR requests, return shared upstream credentials - -2. Dynamic Redirect URIs: - - MCP clients use random localhost ports that change between sessions - - Upstream IDPs require fixed, pre-registered redirect URIs - - Solution: Use proxy's fixed callback URL with upstream, forward to client's dynamic URI - -3. Authorization Code Mapping: - - Upstream returns codes for the proxy's redirect URI - - Clients expect codes for their own redirect URIs - - Solution: Exchange upstream code server-side, issue new code to client - -4. State Parameter Collision: - - Both client and proxy need to maintain state through the flow - - Only one state parameter available in OAuth - - Solution: Use transaction ID as state with upstream, preserve client's state - -5. Token Management: - - Clients may expect different token formats/claims than upstream provides - - Need to track tokens for revocation and refresh - - Solution: Store token relationships, forward upstream tokens transparently - -OAuth Flow Implementation ------------------------- -1. Client Registration (DCR): - - Accept any client registration request - - Store ProxyDCRClient that accepts dynamic redirect URIs - -2. Authorization: - - Store transaction mapping client details to proxy flow - - Redirect to upstream with proxy's fixed redirect URI - - Use transaction ID as state parameter with upstream - -3. Upstream Callback: - - Exchange upstream authorization code for tokens (server-side) - - Generate new authorization code bound to client's PKCE challenge - - Redirect to client's original dynamic redirect URI - -4. Token Exchange: - - Validate client's code and PKCE verifier - - Return previously obtained upstream tokens - - Clean up one-time use authorization code - -5. Token Refresh: - - Forward refresh requests to upstream using authlib - - Handle token rotation if upstream issues new refresh token - - Update local token mappings - -State Management ---------------- -The proxy maintains minimal but crucial state: -- _oauth_transactions: Active authorization flows with client context -- _client_codes: Authorization codes with PKCE challenges and upstream tokens -- _access_tokens, _refresh_tokens: Token storage for revocation -- Token relationship mappings for cleanup and rotation - -Security Considerations ----------------------- -- PKCE enforced end-to-end (client to proxy, proxy to upstream) -- Authorization codes are single-use with short expiry -- Transaction IDs are cryptographically random -- All state is cleaned up after use to prevent replay -- Token validation delegates to upstream provider - -Provider Compatibility ---------------------- -Works with any OAuth 2.0 provider that supports: -- Authorization code flow -- Fixed redirect URI (configured in provider's app settings) -- Standard token endpoint - -Handles provider-specific requirements: -- Google: Ensures minimum scope requirements -- GitHub: Compatible with OAuth Apps and GitHub Apps -- Azure AD: Handles tenant-specific endpoints -- Generic: Works with any spec-compliant provider - - -**Methods:** - -#### `get_client` - -```python -get_client(self, client_id: str) -> OAuthClientInformationFull | None -``` - -Get client information by ID. This is generally the random ID -provided to the DCR client during registration, not the upstream client ID. - -For unregistered clients, returns None (which will raise an error in the SDK). - - -#### `register_client` - -```python -register_client(self, client_info: OAuthClientInformationFull) -> None -``` - -Register a client locally - -When a client registers, we create a ProxyDCRClient that is more -forgiving about validating redirect URIs, since the DCR client's -redirect URI will likely be localhost or unknown to the proxied IDP. The -proxied IDP only knows about this server's fixed redirect URI. - - -#### `authorize` - -```python -authorize(self, client: OAuthClientInformationFull, params: AuthorizationParams) -> str -``` - -Start OAuth transaction and route through consent interstitial. - -Flow: -1. Store transaction with client details and PKCE (if forwarding) -2. Return local /consent URL; browser visits consent first -3. Consent handler redirects to upstream IdP if approved/already approved - - -#### `load_authorization_code` - -```python -load_authorization_code(self, client: OAuthClientInformationFull, authorization_code: str) -> AuthorizationCode | None -``` - -Load authorization code for validation. - -Look up our client code and return authorization code object -with PKCE challenge for validation. - - -#### `exchange_authorization_code` - -```python -exchange_authorization_code(self, client: OAuthClientInformationFull, authorization_code: AuthorizationCode) -> OAuthToken -``` - -Exchange authorization code for FastMCP-issued tokens. - -Implements the token factory pattern: -1. Retrieves upstream tokens from stored authorization code -2. Extracts user identity from upstream token -3. Encrypts and stores upstream tokens -4. Issues FastMCP-signed JWT tokens -5. Returns FastMCP tokens (NOT upstream tokens) - -PKCE validation is handled by the MCP framework before this method is called. - - -#### `load_refresh_token` - -```python -load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str) -> RefreshToken | None -``` - -Load refresh token from local storage. - - -#### `exchange_refresh_token` - -```python -exchange_refresh_token(self, client: OAuthClientInformationFull, refresh_token: RefreshToken, scopes: list[str]) -> OAuthToken -``` - -Exchange FastMCP refresh token for new FastMCP access token. - -Implements two-tier refresh: -1. Verify FastMCP refresh token -2. Look up upstream token via JTI mapping -3. Refresh upstream token with upstream provider -4. Update stored upstream token -5. Issue new FastMCP access token -6. Keep same FastMCP refresh token (unless upstream rotates) - - -#### `load_access_token` - -```python -load_access_token(self, token: str) -> AccessToken | None -``` - -Validate FastMCP JWT by swapping for upstream token. - -This implements the token swap pattern: -1. Verify FastMCP JWT signature (proves it's our token) -2. Look up upstream token via JTI mapping -3. Decrypt upstream token -4. Validate upstream token with provider (GitHub API, JWT validation, etc.) -5. Return upstream validation result - -The FastMCP JWT is a reference token - all authorization data comes -from validating the upstream token via the TokenVerifier. - - -#### `revoke_token` - -```python -revoke_token(self, token: AccessToken | RefreshToken) -> None -``` - -Revoke token locally and with upstream server if supported. - -Removes tokens from local storage and attempts to revoke them with -the upstream server if a revocation endpoint is configured. - - -#### `get_routes` - -```python -get_routes(self, mcp_path: str | None = None) -> list[Route] -``` - -Get OAuth routes with custom proxy token handler. - -This method creates standard OAuth routes and replaces the token endpoint -with our proxy handler that forwards requests to the upstream OAuth server. - -**Args:** -- `mcp_path`: The path where the MCP endpoint is mounted (e.g., "/mcp") -This is used to advertise the resource URL in metadata. +The OauthProxy class has been moved to fastmcp.server.auth.oauth_dcr_proxy.OAuthDCRProxy +for better organization. This module provides a backwards-compatible import. diff --git a/docs/python-sdk/fastmcp-server-auth-oidc_dcr_proxy.mdx b/docs/python-sdk/fastmcp-server-auth-oidc_dcr_proxy.mdx new file mode 100644 index 000000000..2573e9b29 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-auth-oidc_dcr_proxy.mdx @@ -0,0 +1,82 @@ +--- +title: oidc_dcr_proxy +sidebarTitle: oidc_dcr_proxy +--- + +# `fastmcp.server.auth.oidc_dcr_proxy` + + +OIDC Proxy Provider for FastMCP. + +This provider acts as a transparent proxy to an upstream OIDC compliant Authorization +Server. It leverages the OAuthProxy class to handle Dynamic Client Registration and +forwarding of all OAuth flows. + +This implementation is based on: + OpenID Connect Discovery 1.0 - https://openid.net/specs/openid-connect-discovery-1_0.html + OAuth 2.0 Authorization Server Metadata - https://datatracker.ietf.org/doc/html/rfc8414 + + +## Classes + +### `OIDCConfiguration` + + +OIDC Configuration. + + +**Methods:** + +#### `get_oidc_configuration` + +```python +get_oidc_configuration(cls, config_url: AnyHttpUrl) -> Self +``` + +Get the OIDC configuration for the specified config URL. + +**Args:** +- `config_url`: The OIDC config URL +- `strict`: The strict flag for the configuration +- `timeout_seconds`: HTTP request timeout in seconds + + +### `OIDCDCRProxy` + + +OAuth provider that wraps OAuthDCRProxy to provide configuration via an OIDC configuration URL. + +This provider makes it easier to add OAuth protection for any upstream provider +that is OIDC compliant. + + +**Methods:** + +#### `get_oidc_configuration` + +```python +get_oidc_configuration(self, config_url: AnyHttpUrl, strict: bool | None, timeout_seconds: int | None) -> OIDCConfiguration +``` + +Gets the OIDC configuration for the specified configuration URL. + +**Args:** +- `config_url`: The OIDC configuration URL +- `strict`: The strict flag for the configuration +- `timeout_seconds`: HTTP request timeout in seconds + + +#### `get_token_verifier` + +```python +get_token_verifier(self) -> TokenVerifier +``` + +Creates the token verifier for the specified OIDC configuration and arguments. + +**Args:** +- `algorithm`: Optional token verifier algorithm +- `audience`: Optional token verifier audience +- `required_scopes`: Optional token verifier required_scopes +- `timeout_seconds`: HTTP request timeout in seconds + diff --git a/docs/python-sdk/fastmcp-server-auth-oidc_proxy.mdx b/docs/python-sdk/fastmcp-server-auth-oidc_proxy.mdx index 39360e222..1ec3188b0 100644 --- a/docs/python-sdk/fastmcp-server-auth-oidc_proxy.mdx +++ b/docs/python-sdk/fastmcp-server-auth-oidc_proxy.mdx @@ -6,77 +6,8 @@ sidebarTitle: oidc_proxy # `fastmcp.server.auth.oidc_proxy` -OIDC Proxy Provider for FastMCP. +Backwards compatibility shim for oidc_proxy.py -This provider acts as a transparent proxy to an upstream OIDC compliant Authorization -Server. It leverages the OAuthProxy class to handle Dynamic Client Registration and -forwarding of all OAuth flows. - -This implementation is based on: - OpenID Connect Discovery 1.0 - https://openid.net/specs/openid-connect-discovery-1_0.html - OAuth 2.0 Authorization Server Metadata - https://datatracker.ietf.org/doc/html/rfc8414 - - -## Classes - -### `OIDCConfiguration` - - -OIDC Configuration. - - -**Methods:** - -#### `get_oidc_configuration` - -```python -get_oidc_configuration(cls, config_url: AnyHttpUrl) -> Self -``` - -Get the OIDC configuration for the specified config URL. - -**Args:** -- `config_url`: The OIDC config URL -- `strict`: The strict flag for the configuration -- `timeout_seconds`: HTTP request timeout in seconds - - -### `OIDCDCRProxy` - - -OAuth provider that wraps OAuthProxy to provide configuration via an OIDC configuration URL. - -This provider makes it easier to add OAuth protection for any upstream provider -that is OIDC compliant. - - -**Methods:** - -#### `get_oidc_configuration` - -```python -get_oidc_configuration(self, config_url: AnyHttpUrl, strict: bool | None, timeout_seconds: int | None) -> OIDCConfiguration -``` - -Gets the OIDC configuration for the specified configuration URL. - -**Args:** -- `config_url`: The OIDC configuration URL -- `strict`: The strict flag for the configuration -- `timeout_seconds`: HTTP request timeout in seconds - - -#### `get_token_verifier` - -```python -get_token_verifier(self) -> TokenVerifier -``` - -Creates the token verifier for the specified OIDC configuration and arguments. - -**Args:** -- `algorithm`: Optional token verifier algorithm -- `audience`: Optional token verifier audience -- `required_scopes`: Optional token verifier required_scopes -- `timeout_seconds`: HTTP request timeout in seconds +The OIDCProxy class has been moved to fastmcp.server.auth.oidc_dcr_proxy.OIDCDCRProxy +for better organization. This module provides a backwards-compatible import. diff --git a/docs/python-sdk/fastmcp-server-auth-providers-auth0.mdx b/docs/python-sdk/fastmcp-server-auth-providers-auth0.mdx index 097662791..60c537318 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-auth0.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-auth0.mdx @@ -14,10 +14,10 @@ just the configuration URL, client ID, client secret, audience, and base URL. Example: ```python from fastmcp import FastMCP - from fastmcp.server.auth.providers.auth0 import Auth0Provider + from fastmcp.server.auth.providers.auth0 import Auth0DCRProvider # Simple Auth0 OAuth protection - auth = Auth0Provider( + auth = Auth0DCRProvider( config_url="https://auth0.config.url", client_id="your-auth0-client-id", client_secret="your-auth0-client-secret", @@ -31,17 +31,33 @@ Example: ## Classes -### `Auth0ProviderSettings` +### `Auth0DCRProviderSettings` -Settings for Auth0 OIDC provider. +Settings for Auth0 OIDC DCR provider. -### `Auth0Provider` +**Methods:** + +#### `settings_customise_sources` + +```python +settings_customise_sources(cls, settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings) +``` + +### `Auth0DCRProvider` -An Auth0 provider implementation for FastMCP. +An Auth0 DCR provider implementation for FastMCP. This provider is a complete Auth0 integration that's ready to use with just the configuration URL, client ID, client secret, audience, and base URL. + +### `Auth0Provider` + + +Deprecated: Use Auth0DCRProvider instead. + +This alias is provided for backwards compatibility and will be removed in a future version. + diff --git a/docs/python-sdk/fastmcp-server-auth-providers-aws.mdx b/docs/python-sdk/fastmcp-server-auth-providers-aws.mdx index 351732b17..6780a6c7a 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-aws.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-aws.mdx @@ -31,13 +31,21 @@ Example: ## Classes -### `AWSCognitoProviderSettings` +### `AWSCognitoDCRProviderSettings` -Settings for AWS Cognito OAuth provider. +Settings for AWS Cognito OAuth DCR provider. -### `AWSCognitoTokenVerifier` +**Methods:** + +#### `settings_customise_sources` + +```python +settings_customise_sources(cls, settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings) +``` + +### `AWSCognitoTokenVerifier` Token verifier that filters claims to Cognito-specific subset. @@ -45,7 +53,7 @@ Token verifier that filters claims to Cognito-specific subset. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -54,10 +62,10 @@ verify_token(self, token: str) -> AccessToken | None Verify token and filter claims to Cognito-specific subset. -### `AWSCognitoProvider` +### `AWSCognitoDCRProvider` -Complete AWS Cognito OAuth provider for FastMCP. +Complete AWS Cognito OAuth DCR provider for FastMCP. This provider makes it trivial to add AWS Cognito OAuth protection to any FastMCP server using OIDC Discovery. Just provide your Cognito User Pool details, @@ -70,9 +78,17 @@ Features: - Support for Cognito User Pools +### `AWSCognitoProvider` + + +Deprecated: Use AWSCognitoDCRProvider instead. + +This alias is provided for backwards compatibility and will be removed in a future version. + + **Methods:** -#### `get_token_verifier` +#### `get_token_verifier` ```python get_token_verifier(self) -> TokenVerifier diff --git a/docs/python-sdk/fastmcp-server-auth-providers-azure.mdx b/docs/python-sdk/fastmcp-server-auth-providers-azure.mdx index d9748f0ed..899bd6774 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-azure.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-azure.mdx @@ -14,16 +14,24 @@ using the OAuth Proxy pattern for non-DCR OAuth flows. ## Classes -### `AzureProviderSettings` +### `AzureDCRProviderSettings` -Settings for Azure OAuth provider. +Settings for Azure OAuth DCR provider. -### `AzureProvider` +**Methods:** + +#### `settings_customise_sources` + +```python +settings_customise_sources(cls, settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings) +``` + +### `AzureDCRProvider` -Azure (Microsoft Entra) OAuth provider for FastMCP. +Azure (Microsoft Entra) OAuth DCR provider for FastMCP. This provider implements Azure/Microsoft Entra ID authentication using the OAuth Proxy pattern. It supports both organizational accounts and personal @@ -43,9 +51,17 @@ Setup: 6. Get Application (client) ID, Directory (tenant) ID, and client secret +### `AzureProvider` + + +Deprecated: Use AzureDCRProvider instead. + +This alias is provided for backwards compatibility and will be removed in a future version. + + **Methods:** -#### `authorize` +#### `authorize` ```python authorize(self, client: OAuthClientInformationFull, params: AuthorizationParams) -> str diff --git a/docs/python-sdk/fastmcp-server-auth-providers-github.mdx b/docs/python-sdk/fastmcp-server-auth-providers-github.mdx index 5358f2817..93be63306 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-github.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-github.mdx @@ -15,10 +15,10 @@ GitHub's OAuth flow, token validation, and user management. Example: ```python from fastmcp import FastMCP - from fastmcp.server.auth.providers.github import GitHubProvider + from fastmcp.server.auth.providers.github import GitHubDCRProvider # Simple GitHub OAuth protection - auth = GitHubProvider( + auth = GitHubDCRProvider( client_id="your-github-client-id", client_secret="your-github-client-secret" ) @@ -29,13 +29,21 @@ Example: ## Classes -### `GitHubProviderSettings` +### `GitHubDCRProviderSettings` -Settings for GitHub OAuth provider. +Settings for GitHub OAuth DCR provider. -### `GitHubTokenVerifier` +**Methods:** + +#### `settings_customise_sources` + +```python +settings_customise_sources(cls, settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings) +``` + +### `GitHubTokenVerifier` Token verifier for GitHub OAuth tokens. @@ -46,7 +54,7 @@ by calling GitHub's API to check if they're valid and get user info. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -55,10 +63,10 @@ verify_token(self, token: str) -> AccessToken | None Verify GitHub OAuth token by calling GitHub API. -### `GitHubProvider` +### `GitHubDCRProvider` -Complete GitHub OAuth provider for FastMCP. +Complete GitHub OAuth DCR provider for FastMCP. This provider makes it trivial to add GitHub OAuth protection to any FastMCP server. Just provide your GitHub OAuth app credentials and @@ -70,3 +78,11 @@ Features: - User information extraction - Minimal configuration required + +### `GitHubProvider` + + +Deprecated: Use GitHubDCRProvider instead. + +This alias is provided for backwards compatibility and will be removed in a future version. + diff --git a/docs/python-sdk/fastmcp-server-auth-providers-google.mdx b/docs/python-sdk/fastmcp-server-auth-providers-google.mdx index 006c22db3..83d04fb19 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-google.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-google.mdx @@ -15,10 +15,10 @@ Google's OAuth flow, token validation, and user management. Example: ```python from fastmcp import FastMCP - from fastmcp.server.auth.providers.google import GoogleProvider + from fastmcp.server.auth.providers.google import GoogleDCRProvider # Simple Google OAuth protection - auth = GoogleProvider( + auth = GoogleDCRProvider( client_id="your-google-client-id.apps.googleusercontent.com", client_secret="your-google-client-secret" ) @@ -29,13 +29,21 @@ Example: ## Classes -### `GoogleProviderSettings` +### `GoogleDCRProviderSettings` -Settings for Google OAuth provider. +Settings for Google OAuth DCR provider. -### `GoogleTokenVerifier` +**Methods:** + +#### `settings_customise_sources` + +```python +settings_customise_sources(cls, settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings) +``` + +### `GoogleTokenVerifier` Token verifier for Google OAuth tokens. @@ -46,7 +54,7 @@ by calling Google's tokeninfo API to check if they're valid and get user info. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -55,10 +63,10 @@ verify_token(self, token: str) -> AccessToken | None Verify Google OAuth token by calling Google's tokeninfo API. -### `GoogleProvider` +### `GoogleDCRProvider` -Complete Google OAuth provider for FastMCP. +Complete Google OAuth DCR provider for FastMCP. This provider makes it trivial to add Google OAuth protection to any FastMCP server. Just provide your Google OAuth app credentials and @@ -70,3 +78,11 @@ Features: - User information extraction from Google APIs - Minimal configuration required + +### `GoogleProvider` + + +Deprecated: Use GoogleDCRProvider instead. + +This alias is provided for backwards compatibility and will be removed in a future version. + diff --git a/docs/python-sdk/fastmcp-server-auth-providers-workos.mdx b/docs/python-sdk/fastmcp-server-auth-providers-workos.mdx index 60b8ccb67..bd272d139 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-workos.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-workos.mdx @@ -10,7 +10,7 @@ WorkOS authentication providers for FastMCP. This module provides two WorkOS authentication strategies: -1. WorkOSProvider - OAuth proxy for WorkOS Connect applications (non-DCR) +1. WorkOSDCRProvider - OAuth DCR proxy for WorkOS Connect applications 2. AuthKitProvider - DCR-compliant provider for WorkOS AuthKit Choose based on your WorkOS setup and authentication requirements. @@ -18,13 +18,21 @@ Choose based on your WorkOS setup and authentication requirements. ## Classes -### `WorkOSProviderSettings` +### `WorkOSDCRProviderSettings` -Settings for WorkOS OAuth provider. +Settings for WorkOS OAuth DCR provider. -### `WorkOSTokenVerifier` +**Methods:** + +#### `settings_customise_sources` + +```python +settings_customise_sources(cls, settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings) +``` + +### `WorkOSTokenVerifier` Token verifier for WorkOS OAuth tokens. @@ -35,7 +43,7 @@ the /oauth2/userinfo endpoint to check validity and get user info. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -44,16 +52,16 @@ verify_token(self, token: str) -> AccessToken | None Verify WorkOS OAuth token by calling userinfo endpoint. -### `WorkOSProvider` +### `WorkOSDCRProvider` -Complete WorkOS OAuth provider for FastMCP. +Complete WorkOS OAuth DCR provider for FastMCP. -This provider implements WorkOS AuthKit OAuth using the OAuth Proxy pattern. +This provider implements WorkOS AuthKit OAuth using the OAuth DCR Proxy pattern. It provides OAuth2 authentication for users through WorkOS Connect applications. Features: -- Transparent OAuth proxy to WorkOS AuthKit +- Transparent OAuth DCR proxy to WorkOS AuthKit - Automatic token validation via userinfo endpoint - User information extraction from ID tokens - Support for standard OAuth scopes (openid, profile, email) @@ -65,9 +73,17 @@ Setup Requirements: 4. Note your Client ID and Client Secret -### `AuthKitProviderSettings` +### `WorkOSProvider` -### `AuthKitProvider` + +Deprecated: Use WorkOSDCRProvider instead. + +This alias is provided for backwards compatibility and will be removed in a future version. + + +### `AuthKitProviderSettings` + +### `AuthKitProvider` AuthKit metadata provider for DCR (Dynamic Client Registration). @@ -93,7 +109,7 @@ https://workos.com/docs/authkit/mcp/integrating/token-verification **Methods:** -#### `get_routes` +#### `get_routes` ```python get_routes(self, mcp_path: str | None = None) -> list[Route] diff --git a/docs/python-sdk/fastmcp-server-http.mdx b/docs/python-sdk/fastmcp-server-http.mdx index d06e214a0..40ae6fb9b 100644 --- a/docs/python-sdk/fastmcp-server-http.mdx +++ b/docs/python-sdk/fastmcp-server-http.mdx @@ -7,13 +7,13 @@ sidebarTitle: http ## Functions -### `set_http_request` +### `set_http_request` ```python set_http_request(request: Request) -> Generator[Request, None, None] ``` -### `create_base_app` +### `create_base_app` ```python create_base_app(routes: list[BaseRoute], middleware: list[Middleware], debug: bool = False, lifespan: Callable | None = None) -> StarletteWithLifespan @@ -32,7 +32,7 @@ Create a base Starlette app with common middleware and routes. - A Starlette application -### `create_sse_app` +### `create_sse_app` ```python create_sse_app(server: FastMCP[LifespanResultT], message_path: str, sse_path: str, auth: AuthProvider | None = None, debug: bool = False, routes: list[BaseRoute] | None = None, middleware: list[Middleware] | None = None) -> StarletteWithLifespan @@ -54,7 +54,7 @@ Returns: A Starlette application with RequestContextMiddleware -### `create_streamable_http_app` +### `create_streamable_http_app` ```python create_streamable_http_app(server: FastMCP[LifespanResultT], streamable_http_path: str, event_store: EventStore | None = None, auth: AuthProvider | None = None, json_response: bool = False, stateless_http: bool = False, debug: bool = False, routes: list[BaseRoute] | None = None, middleware: list[Middleware] | None = None) -> StarletteWithLifespan @@ -80,23 +80,23 @@ Return an instance of the StreamableHTTP server app. ## Classes -### `StreamableHTTPASGIApp` +### `StreamableHTTPASGIApp` ASGI application wrapper for Streamable HTTP server transport. -### `StarletteWithLifespan` +### `StarletteWithLifespan` **Methods:** -#### `lifespan` +#### `lifespan` ```python lifespan(self) -> Lifespan[Starlette] ``` -### `RequestContextMiddleware` +### `RequestContextMiddleware` Middleware that stores each request in a ContextVar