mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 07:09:11 +02:00
233 lines
7.8 KiB
Text
233 lines
7.8 KiB
Text
---
|
|
title: Bearer Token Authentication
|
|
sidebarTitle: Bearer Auth
|
|
description: Secure your FastMCP server's HTTP endpoints by validating JWT Bearer tokens.
|
|
icon: key
|
|
tag: NEW
|
|
---
|
|
|
|
import { VersionBadge } from "/snippets/version-badge.mdx"
|
|
|
|
<VersionBadge version="2.6.0" />
|
|
<Tip>
|
|
Authentication and authorization are only relevant for HTTP-based transports.
|
|
</Tip>
|
|
|
|
<Note>
|
|
The [MCP specification](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization) requires servers to implement full OAuth 2.1 authorization flows with dynamic client registration, server metadata discovery, and complete token endpoints. FastMCP's Bearer Token authentication provides a simpler, more practical alternative by directly validating pre-issued JWT tokens—ideal for service-to-service communication and programmatic environments where full OAuth flows may be impractical, and in accordance with how the MCP ecosystem is pragmatically evolving. However, please note that since it doesn't implement the full OAuth 2.1 flow, this implementation does not strictly comply with the MCP specification.
|
|
</Note>
|
|
|
|
Bearer Token authentication is a common way to secure HTTP-based APIs. In this model, the client sends a token (usually a JSON Web Token or JWT) in the `Authorization` header with the "Bearer" scheme. The server then validates this token to grant or deny access.
|
|
|
|
FastMCP supports Bearer Token authentication for its HTTP-based transports (`http` and `sse`), allowing you to protect your server from unauthorized access.
|
|
|
|
## Authentication Strategy
|
|
|
|
FastMCP uses **asymmetric encryption** for token validation, which provides a clean security separation between token issuers and FastMCP servers. This approach means:
|
|
|
|
- **No shared secrets**: Your FastMCP server never needs access to private keys or client secrets
|
|
- **Public key verification**: The server only needs a public key (or JWKS endpoint) to verify token signatures
|
|
- **Secure token issuance**: Tokens are signed by an external service using a private key that never leaves the issuer
|
|
- **Scalable architecture**: Multiple FastMCP servers can validate tokens without coordinating secrets
|
|
|
|
This design allows you to integrate FastMCP servers into existing authentication infrastructures without compromising security boundaries.
|
|
|
|
## Configuration
|
|
|
|
To enable Bearer Token validation on your FastMCP server, use the `BearerAuthProvider` class. This provider validates incoming JWTs by verifying signatures, checking expiration, and optionally validating claims.
|
|
|
|
<Warning>
|
|
The `BearerAuthProvider` validates tokens; it does **not** issue them (or implement any part of an OAuth flow). You'll need to generate tokens separately, either using FastMCP utilities or an external Identity Provider (IdP) or OAuth 2.1 Authorization Server.
|
|
</Warning>
|
|
|
|
### Basic Setup
|
|
|
|
To configure bearer token authentication, instantiate a `BearerAuthProvider` instance and pass it to the `auth` parameter of the `FastMCP` instance.
|
|
|
|
The `BearerAuthProvider` requires either a static public key or a JWKS URI (but not both!) in order to verify the token's signature. All other parameters are optional -- if they are provided, they will be used as additional validation criteria.
|
|
|
|
```python {2, 10}
|
|
from fastmcp import FastMCP
|
|
from fastmcp.server.auth import BearerAuthProvider
|
|
|
|
auth = BearerAuthProvider(
|
|
jwks_uri="https://my-identity-provider.com/.well-known/jwks.json",
|
|
issuer="https://my-identity-provider.com/",
|
|
audience="my-mcp-server"
|
|
)
|
|
|
|
mcp = FastMCP(name="My MCP Server", auth=auth)
|
|
```
|
|
|
|
### Configuration Parameters
|
|
|
|
<Card icon="code" title="BearerAuthProvider Configuration">
|
|
<ParamField body="public_key" type="str">
|
|
RSA public key in PEM format for static key validation. Required if `jwks_uri` is not provided
|
|
</ParamField>
|
|
|
|
<ParamField body="jwks_uri" type="str">
|
|
URL for JSON Web Key Set endpoint. Required if `public_key` is not provided
|
|
</ParamField>
|
|
|
|
<ParamField body="issuer" type="str | None">
|
|
Expected JWT `iss` claim value
|
|
</ParamField>
|
|
|
|
<ParamField body="audience" type="str | None">
|
|
Expected JWT `aud` claim value
|
|
</ParamField>
|
|
|
|
<ParamField body="required_scopes" type="list[str] | None">
|
|
Global scopes required for all requests
|
|
</ParamField>
|
|
</Card>
|
|
|
|
#### Public Key
|
|
|
|
If you have a public key in PEM format, you can provide it to the `BearerAuthProvider` as a string.
|
|
|
|
```python {12}
|
|
from fastmcp.server.auth import BearerAuthProvider
|
|
import inspect
|
|
|
|
public_key_pem = inspect.cleandoc(
|
|
"""
|
|
-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy...
|
|
-----END PUBLIC KEY-----
|
|
"""
|
|
)
|
|
|
|
auth = BearerAuthProvider(public_key=public_key_pem)
|
|
```
|
|
|
|
#### JWKS URI
|
|
|
|
```python
|
|
provider = BearerAuthProvider(
|
|
jwks_uri="https://idp.example.com/.well-known/jwks.json"
|
|
)
|
|
```
|
|
|
|
<Note>
|
|
JWKS is recommended for production as it supports automatic key rotation and multiple signing keys.
|
|
</Note>
|
|
|
|
## Generating Tokens
|
|
|
|
For development and testing, FastMCP provides the `RSAKeyPair` utility class to generate tokens without needing an external OAuth provider.
|
|
|
|
<Warning>
|
|
The `RSAKeyPair` utility is intended for development and testing only. For production, use a proper OAuth 2.1 Authorization Server or Identity Provider.
|
|
</Warning>
|
|
### Basic Token Generation
|
|
|
|
```python
|
|
from fastmcp import FastMCP
|
|
from fastmcp.server.auth import BearerAuthProvider
|
|
from fastmcp.server.auth.providers.bearer import RSAKeyPair
|
|
|
|
# Generate a new key pair
|
|
key_pair = RSAKeyPair.generate()
|
|
|
|
# Configure the auth provider with the public key
|
|
auth = BearerAuthProvider(
|
|
public_key=key_pair.public_key,
|
|
issuer="https://dev.example.com",
|
|
audience="my-dev-server"
|
|
)
|
|
|
|
mcp = FastMCP(name="Development Server", auth=auth)
|
|
|
|
# Generate a token for testing
|
|
token = key_pair.create_token(
|
|
subject="dev-user",
|
|
issuer="https://dev.example.com",
|
|
audience="my-dev-server",
|
|
scopes=["read", "write"]
|
|
)
|
|
|
|
print(f"Test token: {token}")
|
|
```
|
|
|
|
### Token Creation Parameters
|
|
|
|
The `create_token()` method accepts these parameters:
|
|
|
|
<Card icon="code" title="create_token() Parameters">
|
|
<ParamField body="subject" type="str" default="fastmcp-user">
|
|
JWT subject claim (usually user ID)
|
|
</ParamField>
|
|
|
|
<ParamField body="issuer" type="str" default="https://fastmcp.example.com">
|
|
JWT issuer claim
|
|
</ParamField>
|
|
|
|
<ParamField body="audience" type="str | None">
|
|
JWT audience claim
|
|
</ParamField>
|
|
|
|
<ParamField body="scopes" type="list[str] | None">
|
|
OAuth scopes to include
|
|
</ParamField>
|
|
|
|
<ParamField body="expires_in_seconds" type="int" default="3600">
|
|
Token expiration time in seconds
|
|
</ParamField>
|
|
|
|
<ParamField body="additional_claims" type="dict | None">
|
|
Extra claims to include in the token
|
|
</ParamField>
|
|
|
|
<ParamField body="kid" type="str | None">
|
|
Key ID for JWKS lookup
|
|
</ParamField>
|
|
</Card>
|
|
|
|
|
|
## Accessing Token Claims
|
|
|
|
Once authenticated, your tools, resources, or prompts can access token information using the `get_access_token()` dependency function:
|
|
|
|
```python
|
|
from fastmcp import FastMCP, Context, ToolError
|
|
from fastmcp.server.dependencies import get_access_token, AccessToken
|
|
|
|
@mcp.tool
|
|
async def get_my_data(ctx: Context) -> dict:
|
|
access_token: AccessToken = get_access_token()
|
|
|
|
user_id = access_token.client_id # From JWT 'sub' or 'client_id' claim
|
|
user_scopes = access_token.scopes
|
|
|
|
if "data:read_sensitive" not in user_scopes:
|
|
raise ToolError("Insufficient permissions: 'data:read_sensitive' scope required.")
|
|
|
|
return {
|
|
"user": user_id,
|
|
"sensitive_data": f"Private data for {user_id}",
|
|
"granted_scopes": user_scopes
|
|
}
|
|
```
|
|
|
|
### AccessToken Properties
|
|
|
|
<Card icon="code" title="AccessToken Properties">
|
|
<ParamField body="token" type="str">
|
|
The raw JWT string
|
|
</ParamField>
|
|
|
|
<ParamField body="client_id" type="str">
|
|
Authenticated principal identifier
|
|
</ParamField>
|
|
|
|
<ParamField body="scopes" type="list[str]">
|
|
Granted scopes
|
|
</ParamField>
|
|
|
|
<ParamField body="expires_at" type="datetime | None">
|
|
Token expiration timestamp
|
|
</ParamField>
|
|
</Card>
|
|
|