New in version: 2.12.0
The OAuth proxy enables FastMCP servers to authenticate with OAuth providers that don’t support Dynamic Client Registration (DCR). This includes virtually all traditional OAuth providers: GitHub, Google, Azure, AWS, Discord, Facebook, and most enterprise identity systems. For providers that do support DCR (like Descope and WorkOS AuthKit), use RemoteAuthProvider instead.
MCP clients expect to register automatically and obtain credentials on the fly, but traditional providers require manual app registration through their developer consoles. The OAuth proxy bridges this gap by presenting a DCR-compliant interface to MCP clients while using your pre-registered credentials with the upstream provider. When a client attempts to register, the proxy returns your fixed credentials. When a client initiates authorization, the proxy handles the complexity of callback forwarding—storing the client’s dynamic callback URL, using its own fixed callback with the provider, then forwarding back to the client after token exchange.
This approach enables any MCP client (whether using random localhost ports or fixed URLs like Claude.ai) to authenticate with any traditional OAuth provider, all while maintaining full OAuth 2.1 and PKCE security.
For providers that support OIDC discovery (Auth0, Google with OIDC
configuration, Azure AD), consider using
OIDC Proxy for automatic configuration. OIDC Proxy
extends the OAuth proxy to automatically discover endpoints from the provider’s
/.well-known/openid-configuration URL, simplifying setup.Implementation
Provider Setup Requirements
Before using the OAuth proxy, you need to register your application with your OAuth provider:- Register your application in the provider’s developer console (GitHub Settings, Google Cloud Console, Azure Portal, etc.)
- Configure the redirect URI as your FastMCP server URL plus your chosen callback path:
- Default:
https://your-server.com/auth/callback - Custom:
https://your-server.com/your/custom/path(if you setredirect_path) - Development:
http://localhost:8000/auth/callback
- Default:
- Obtain your credentials: Client ID and Client Secret
- Note the OAuth endpoints: Authorization URL and Token URL (usually found in the provider’s OAuth documentation)
Basic Setup
Here’s how to implement the OAuth proxy with any provider:Configuration Parameters
OAuthProxy Parameters
URL of your OAuth provider’s authorization endpoint (e.g.,
https://github.com/login/oauth/authorize)URL of your OAuth provider’s token endpoint (e.g.,
https://github.com/login/oauth/access_token)Client ID from your registered OAuth application
Client secret from your registered OAuth application
A
TokenVerifier instance to validate the
provider’s tokensPublic URL where OAuth endpoints will be accessible, including any mount path (e.g.,
https://your-server.com/api).This URL is used to construct OAuth callback URLs and operational endpoints. When mounting under a path prefix, include that prefix in base_url. Use issuer_url separately to specify where auth server metadata is located (typically at root level).Path for OAuth callbacks. Must match the redirect URI configured in your OAuth
application
Optional URL of provider’s token revocation endpoint
Issuer URL for OAuth authorization server metadata (defaults to Without
base_url).When mounting your MCP server under a path prefix (e.g., /api), set this to your root-level URL to avoid 404 logs during OAuth discovery. MCP clients try path-scoped discovery first per RFC 8414, which will fail if your auth server metadata is at the root level.Example with mounting:issuer_url, clients will attempt /.well-known/oauth-authorization-server/api (404) before falling back to /.well-known/oauth-authorization-server (success). Setting issuer_url to the root eliminates the 404 attempt.When to use:- Default (
None): Usebase_urlas issuer - simple deployments at root path - Root-level URL: Mounting under a path prefix - avoids 404 logs
Optional URL to your service documentation
Whether to forward PKCE (Proof Key for Code Exchange) to the upstream OAuth
provider. When enabled and the client uses PKCE, the proxy generates its own
PKCE parameters to send upstream while separately validating the client’s
PKCE. This ensures end-to-end PKCE security at both layers (client-to-proxy
and proxy-to-upstream). -
True (default): Forward PKCE for providers that
support it (Google, Azure, AWS, GitHub, etc.) - False: Disable only if upstream
provider doesn’t support PKCEToken endpoint authentication method for the upstream OAuth server. Controls
how the proxy authenticates when exchanging authorization codes and refresh
tokens with the upstream provider. -
"client_secret_basic": Send credentials
in Authorization header (most common) - "client_secret_post": Send
credentials in request body (required by some providers) - "none": No
authentication (for public clients) - None (default): Uses authlib’s default
(typically "client_secret_basic") Set this if your provider requires a
specific authentication method and the default doesn’t work.List of allowed redirect URI patterns for MCP clients. Patterns support
wildcards (e.g.,
"http://localhost:*", "https://*.example.com/*"). -
None (default): All redirect URIs allowed (for MCP/DCR compatibility) -
Empty list []: No redirect URIs allowed - Custom list: Only matching
patterns allowed These patterns apply to MCP client loopback redirects, NOT
the upstream OAuth app redirect URI.List of all possible valid scopes for the OAuth provider. These are advertised
to clients through the
/.well-known endpoints. Defaults to required_scopes
from your TokenVerifier if not specified.Additional parameters to forward to the upstream authorization endpoint. Useful for provider-specific parameters that aren’t part of the standard OAuth2 flow.For example, Auth0 requires an These parameters are added to every authorization request sent to the upstream provider.
audience parameter to issue JWT tokens:Additional parameters to forward to the upstream token endpoint during code exchange and token refresh. Useful for provider-specific requirements during token operations.For example, some providers require additional context during token exchange:These parameters are included in all token requests to the upstream provider.
New in version: 2.13.0Storage backend for persisting OAuth client registrations and upstream tokens.Default behavior:
By default, clients are automatically persisted to an encrypted disk store, allowing them to survive server restarts as long as the filesystem remains accessible. This means MCP clients only need to register once and can reconnect seamlessly. The disk store is encrypted using a key derived from the JWT Signing Key (which is derived from the upstream client secret by default). For client registrations to survive upstream client secret rotation, you should provide a JWT Signing Key or your own client_storage.For production deployments with multiple servers or cloud deployments, see Storage Backends for available options.Testing with in-memory storage (unencrypted):New in version: 2.13.0Secret used to sign FastMCP JWT tokens issued to clients. Accepts any string or bytes - will be derived into a proper 32-byte cryptographic key using HKDF.Default behavior (None):
Derives a 32-byte key using PBKDF2 from the upstream client secret.For production:
Provide an explicit secret (e.g., from environment variable) to use a fixed key instead of the key derived from the upstream client secret. This allows you to manage keys securely in cloud environments, allows keys to work across multiple instances, and allows you to rotate keys without losing client registrations.Whether to require user consent before authorizing MCP clients. When enabled (default), users see a consent screen that displays which client is requesting access, preventing confused deputy attacks by ensuring users explicitly approve new clients.Default behavior (True):
Users see a consent screen on first authorization. Consent choices are remembered via signed cookies, so users only need to approve each client once. This protects against malicious clients impersonating the user.Disabling consent (False):
Authorization proceeds directly to the upstream provider without user confirmation. Only use this for local development or testing environments where the security trade-off is acceptable.
Using Built-in Providers
FastMCP includes pre-configured providers for common services:GitHubProvider, GoogleProvider, and others. These handle token verification automatically.
Token Verification
The OAuth proxy requires a compatibleTokenVerifier to validate tokens from your provider. Different providers use different token formats:
- JWT tokens (Google, Azure): Use
JWTVerifierwith the provider’s JWKS endpoint - Opaque tokens with RFC 7662 introspection (Auth0, Okta, WorkOS): Use
IntrospectionTokenVerifier - Opaque tokens (provider-specific) (GitHub, Discord): Use provider-specific verifiers like
GitHubTokenVerifier
Scope Configuration
OAuth scopes control what permissions your application requests from users. They’re configured through yourTokenVerifier (required for the OAuth proxy to validate tokens from your provider). Set required_scopes to automatically request the permissions your application needs:
Custom Parameters
Some OAuth providers require additional parameters beyond the standard OAuth2 flow. Useextra_authorize_params and extra_token_params to pass provider-specific requirements. For example, Auth0 requires an audience parameter to issue JWT tokens instead of opaque tokens:
resource parameters from MCP clients to upstream providers that support them.
OAuth Flow
The flow diagram above illustrates the complete OAuth proxy pattern. Let’s understand each phase:Registration Phase
When an MCP client calls/register with its dynamic callback URL, the proxy responds with your pre-configured upstream credentials. The client stores these credentials believing it has registered a new app. Meanwhile, the proxy records the client’s callback URL for later use.
Authorization Phase
The client initiates OAuth by redirecting to the proxy’s/authorize endpoint. The proxy:
- Stores the client’s transaction with its PKCE challenge
- Generates its own PKCE parameters for upstream security
- Shows the user a consent page with the client’s details, redirect URI, and requested scopes
- If the user approves (or the client was previously approved), redirects to the upstream provider using the fixed callback URL
Callback Phase
After user authorization, the provider redirects back to the proxy’s fixed callback URL. The proxy:- Exchanges the authorization code for tokens with the provider
- Stores these tokens temporarily
- Generates a new authorization code for the client
- Redirects to the client’s original dynamic callback URL
Token Exchange Phase
Finally, the client exchanges its authorization code with the proxy to receive the provider’s tokens. The proxy validates the client’s PKCE verifier before returning the stored tokens. This entire flow is transparent to the MCP client—it experiences a standard OAuth flow with dynamic registration, unaware that a proxy is managing the complexity behind the scenes.Token Architecture
The OAuth proxy implements a token factory pattern: instead of directly forwarding tokens from the upstream OAuth provider, it issues its own JWT tokens to MCP clients. This maintains proper OAuth 2.0 token audience boundaries and enables better security controls. How it works: When an MCP client completes authorization, the proxy:- Receives upstream tokens from the OAuth provider (GitHub, Google, etc.)
- Encrypts and stores these tokens using Fernet encryption (AES-128-CBC + HMAC-SHA256)
- Issues FastMCP JWT tokens to the client, signed with HS256
- FastMCP validates the JWT signature, expiration, issuer, and audience
- Looks up the upstream token using the JTI from the validated JWT
- Decrypts and validates the upstream token with the provider
PKCE Forwarding
The OAuth proxy automatically handles PKCE (Proof Key for Code Exchange) when working with providers that support or require it. The proxy generates its own PKCE parameters to send upstream while separately validating the client’s PKCE, ensuring end-to-end security at both layers. This is enabled by default via theforward_pkce parameter and works seamlessly with providers like Google, Azure AD, and GitHub. Only disable it for legacy providers that don’t support PKCE:
Redirect URI Validation
While the OAuth proxy accepts all redirect URIs by default (for DCR compatibility), you can restrict which clients can connect by specifying allowed patterns:Security
Key and Storage Management
New in version: 2.13.0
The OAuth proxy requires cryptographic keys for JWT signing and storage encryption, plus persistent storage to maintain valid tokens across server restarts.
Default behavior (appropriate for development only):
- Mac/Windows: FastMCP automatically generates keys and stores them in your system keyring. Storage defaults to disk. Tokens survive server restarts. This is only suitable for development and local testing.
- Linux: Keys are ephemeral (random salt at startup). Storage defaults to memory. Tokens become invalid on server restart.
jwt_signing_key (for signing FastMCP JWTs), and a shared client_storage backend (for storing tokens). Both are required for production deployments. Use a network-accessible storage backend like Redis or DynamoDB rather than local disk storage. Wrap your storage in FernetEncryptionWrapper to encrypt sensitive OAuth tokens at rest (see the client_storage parameter documentation above for examples). The keys accept any secret string and derive proper cryptographic keys using HKDF. See OAuth Token Security and Storage Backends for complete production setup.
Confused Deputy Attacks
New in version: 2.13.0
A confused deputy attack allows a malicious client to steal your authorization by tricking you into granting it access under your identity.
The OAuth proxy works by bridging DCR clients to traditional auth providers, which means that multiple MCP clients connect through a single upstream OAuth application. An attacker can exploit this shared application by registering a malicious client with their own redirect URI, then sending you an authorization link. When you click it, your browser goes through the OAuth flow—but since you may have already authorized this OAuth app before, the provider might auto-approve the request. The authorization code then gets sent to the attacker’s redirect URI instead of a legitimate client, giving them access under your credentials.
Mitigation
FastMCP’s OAuth proxy requires you to explicitly consent whenever any new or unrecognized client attempts to connect to your server. Before any authorization happens, you see a consent page showing the client’s details, redirect URI, and requested scopes. This gives you the opportunity to review and deny suspicious requests. Once you approve a client, it’s remembered so you don’t see the consent page again for that client. The consent mechanism is implemented with CSRF tokens and cryptographically signed cookies to prevent tampering.
- MCP Security Best Practices - Official specification guidance
- Confused Deputy Attacks Explained - Detailed walkthrough by Den Delimarsky
Environment Configuration
New in version: 2.12.1
For production deployments, configure the OAuth proxy through environment variables instead of hardcoding credentials:

