Skip to main content
Version: 0.2.0-beta.1

Configure Bearer auth in MCP server

With the latest MCP specification, your MCP server acts as a Resource Server that validates access tokens for protected resources. MCP Auth provides various ways to configure Bearer authorization:

  • JWT (JSON Web Token) mode: A built-in authorization method that verifies JWTs with claim assertions.
  • Custom mode: Allows you to implement your own authorization logic.

The Bearer auth middleware now requires specifying which resource the endpoint belongs to, enabling proper token validation against the configured authorization servers.

Configure Bearer auth with JWT mode

If your OAuth / OIDC provider issues JWTs for authorization, you can use the built-in JWT mode in MCP Auth. It verifies the JWT signature, expiration, and other claims you specify; then it populates the authentication information in the request context for further processing in your MCP implementation.

Scope validation

Here's an example of the basic scope validation:

from mcpauth import MCPAuth
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.routing import Mount
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("MyMCPServer")
mcp_auth = MCPAuth(
    # Initialize with your auth server config
)
bearer_auth = mcp_auth.bearer_auth_middleware("jwt", 
    resource="https://api.example.com",  # Specify which resource this endpoint belongs to
    audience="https://api.example.com",  # Enable audience validation for security
    required_scopes=["read", "write"] 
)

app = Starlette(
    routes=[Mount('/', app=mcp.sse_app(), middleware=[Middleware(bearer_auth)])]
)

In the example above, we specified that the JWT requires the read and write scopes. If the JWT does not contain any of these scopes, the request will be rejected with a 403 Forbidden error.

Audience validation (RFC 8707)

For secure token validation, you should always include audience validation by specifying the audience parameter. This validates the aud (audience) claim in the JWT to ensure that the token was specifically issued for your MCP server resource.

Audience Validation

The audience parameter is required by the OAuth 2.0 specification for secure token validation. However, it is currently optional to maintain compatibility with authorization servers that do not yet support resource identifiers. For security reasons, please always include the audience parameter when possible. Future versions will enforce audience validation as mandatory to fully comply with the specification.

The audience value should typically match your resource identifier:

bearer_auth = mcp_auth.bearer_auth_middleware(
    "jwt",
    resource="https://api.example.com",  # Specify which resource this endpoint belongs to
    audience="https://api.example.com",  # Enable audience validation for security
    required_scopes=["read", "write"]
)

In the example above, MCP Auth will validate both the aud claim in the JWT and the required scopes.

Provide custom options to the JWT verification

You can also provide custom options to the underlying JWT verification library:

In Python SDK, we use PyJWT for JWT verification. You can the following options:

  • leeway: Allow a certain amount of leeway when verifying the JWT expiration time (in seconds). Default is 60 seconds.
bearer_auth = mcp_auth.bearer_auth_middleware(
    "jwt",
    resource="https://api.example.com",
    audience="https://api.example.com",
    required_scopes=["read", "write"],
    leeway=10,  # Reduce clock skew by allowing 10 seconds leeway
)

Configure Bearer auth with custom verification

If your OAuth / OIDC provider does not issue JWTs, or you want to implement your own authorization logic, MCP Auth allows you to create a custom verification function:

info

Since the Bearer auth middleware will check against issuer (iss), audience (aud), and required scopes (scope) with the given verification result, there's no need to implement these checks in your custom verification function. You can focus on verifying the token validity (e.g., signature, expiration, etc.) and returning the auth info object.

from mcpauth.exceptions import MCPAuthJwtVerificationException, MCPAuthJwtVerificationExceptionCode
from mcpauth.types import AuthInfo

async def custom_verification(token: str) -> AuthInfo:
    # Implement your custom verification logic here
    info = await verify_token(token)
    if not info:
        raise MCPAuthJwtVerificationException(
            MCPAuthJwtVerificationExceptionCode.JWT_VERIFICATION_FAILED
        )
    return info  # Return the auth info object

bearer_auth = mcp_auth.bearer_auth_middleware(
    custom_verification,
    resource="https://api.example.com",
    audience="https://api.example.com",  # Enable audience validation for security
    required_scopes=["read", "write"]
)

Apply Bearer auth in your MCP server

To protect your MCP server with Bearer auth, you need to apply the Bearer auth middleware to your MCP server instance.

bearer_auth = mcp_auth.bearer_auth_middleware("jwt", 
    resource="https://api.example.com",
    audience="https://api.example.com",  # Enable audience validation for security
    required_scopes=["read", "write"]
)
app = Starlette(
    routes=[Mount('/', app=mcp.sse_app(), middleware=[Middleware(bearer_auth)])]
)

This will ensure that all incoming requests are authenticated and authorized according to the configured Bearer auth settings, and the auth information will be available in the request context.

You can then access the information in your MCP server implementation:

@mcp.tool()
async def whoami() -> dict:
    # `mcp_auth.auth_info` is the context object for the current request
    auth_info = mcp_auth.auth_info
    print(f"Authenticated user: {auth_info.subject}")
    return {"subject": auth_info.subject}