diff --git a/docs/servers/auth/bearer.mdx b/docs/servers/auth/bearer.mdx
index 15df171f6..7db7085a6 100644
--- a/docs/servers/auth/bearer.mdx
+++ b/docs/servers/auth/bearer.mdx
@@ -53,6 +53,7 @@ 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/",
+ algorithm="RS512",
audience="my-mcp-server"
)
@@ -74,6 +75,10 @@ mcp = FastMCP(name="My MCP Server", auth=auth)
Expected JWT `iss` claim value
+
+ Algorithm for decoding JWT token. Defaults to 'RS256'
+
+
Expected JWT `aud` claim value
diff --git a/src/fastmcp/server/auth/providers/bearer.py b/src/fastmcp/server/auth/providers/bearer.py
index edb7abb3f..3656783cf 100644
--- a/src/fastmcp/server/auth/providers/bearer.py
+++ b/src/fastmcp/server/auth/providers/bearer.py
@@ -1,6 +1,6 @@
import time
from dataclasses import dataclass
-from typing import Any
+from typing import Any, Literal
import httpx
from authlib.jose import JsonWebKey, JsonWebToken
@@ -28,6 +28,7 @@ from fastmcp.server.auth.auth import (
from fastmcp.utilities.logging import get_logger
+
class JWKData(TypedDict, total=False):
"""JSON Web Key data structure."""
@@ -113,6 +114,7 @@ class RSAKeyPair:
Returns:
Signed JWT token string
"""
+ #TODO : Add support for configurable algorithms
jwt = JsonWebToken(["RS256"])
now = int(time.time())
@@ -151,18 +153,19 @@ class RSAKeyPair:
class BearerAuthProvider(OAuthProvider):
"""
Simple JWT Bearer Token validator for hosted MCP servers.
- Uses RS256 asymmetric encryption. Supports either static public key
+ Uses RS256 asymmetric encryption by default but supports all JWA algorithms. Supports either static public key
or JWKS URI for key rotation.
Note that this provider DOES NOT permit client registration or revocation, or any OAuth flows.
It is intended to be used with a control plane that manages clients and tokens.
"""
-
+ #TODO: Add support for configurable algorithms 'e.g. algorithm= HS256, ES256, etc.'
def __init__(
self,
public_key: str | None = None,
jwks_uri: str | None = None,
issuer: str | None = None,
+ algorithm: str | None = None,
audience: str | list[str] | None = None,
required_scopes: list[str] | None = None,
):
@@ -173,6 +176,7 @@ class BearerAuthProvider(OAuthProvider):
public_key: RSA public key in PEM format (for static key)
jwks_uri: URI to fetch keys from (for key rotation)
issuer: Expected issuer claim (optional)
+ algorithm: Algorithm to use for verification (optional, defaults to RS256)
audience: Expected audience claim - can be a string or list of strings (optional)
required_scopes: List of required scopes for access (optional)
"""
@@ -180,7 +184,12 @@ class BearerAuthProvider(OAuthProvider):
raise ValueError("Either public_key or jwks_uri must be provided")
if public_key and jwks_uri:
raise ValueError("Provide either public_key or jwks_uri, not both")
-
+
+ if not algorithm:
+ algorithm = "RS256"
+ if algorithm not in {"HS256","HS384","HS512","RS256","RS384","RS512", "ES256", "ES384","ES512","PS256","PS384", "PS512"}:
+ raise ValueError(f"Unsupported algorithm: {algorithm}.")
+
# Only pass issuer to parent if it's a valid URL, otherwise use default
# This allows the issuer claim validation to work with string issuers per RFC 7519
try:
@@ -196,11 +205,14 @@ class BearerAuthProvider(OAuthProvider):
required_scopes=required_scopes,
)
+ self.algorithm = algorithm
self.issuer = issuer
self.audience = audience
self.public_key = public_key
self.jwks_uri = jwks_uri
- self.jwt = JsonWebToken(["RS256"])
+
+ # TODO : Add support for configurable algorithms
+ self.jwt = JsonWebToken([self.algorithm]) # Use RS256 by default
self.logger = get_logger(__name__)
# Simple JWKS cache
diff --git a/src/fastmcp/server/auth/providers/bearer_env.py b/src/fastmcp/server/auth/providers/bearer_env.py
index 308f5fcd7..dfbd96146 100644
--- a/src/fastmcp/server/auth/providers/bearer_env.py
+++ b/src/fastmcp/server/auth/providers/bearer_env.py
@@ -17,6 +17,7 @@ class EnvBearerAuthProviderSettings(BaseSettings):
public_key: str | None = None
jwks_uri: str | None = None
issuer: str | None = None
+ algorithm: str | None = None
audience: str | None = None
required_scopes: list[str] | None = None
@@ -33,6 +34,7 @@ class EnvBearerAuthProvider(BearerAuthProvider):
public_key: str | None | EllipsisType = ...,
jwks_uri: str | None | EllipsisType = ...,
issuer: str | None | EllipsisType = ...,
+ algorithm: str | None | EllipsisType = ...,
audience: str | None | EllipsisType = ...,
required_scopes: list[str] | None | EllipsisType = ...,
):
@@ -43,6 +45,7 @@ class EnvBearerAuthProvider(BearerAuthProvider):
public_key: RSA public key in PEM format (for static key)
jwks_uri: URI to fetch keys from (for key rotation)
issuer: Expected issuer claim (optional)
+ algorithm: Algorithm to use for verification (optional)
audience: Expected audience claim (optional)
required_scopes: List of required scopes for access (optional)
"""
@@ -50,6 +53,7 @@ class EnvBearerAuthProvider(BearerAuthProvider):
"public_key": public_key,
"jwks_uri": jwks_uri,
"issuer": issuer,
+ "algorithm": algorithm,
"audience": audience,
"required_scopes": required_scopes,
}