Skip to main content

Configure Bearer auth in MCP server

MCP Auth provides various ways to configure Bearer authorization in your MCP server:

  • 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.

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", 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.

Resource indicator validation (RFC 8707)

If your provider is based on OIDC, or supports the Resource Indicator extension, you may also specify the audience option to validate the aud (audience) claim in the JWT. This is useful to ensure that the JWT is intended for your MCP server.

Check your provider's documentation to see if it supports the Resource Indicator extension and how to configure it. Some providers may use other terms like "audience", "API resource", or "API indicator" to refer to the same concept.

Once the resource indicator is configured, you can specify it in the bearerAuth middleware:

bearer_auth = mcp_auth.bearer_auth_middleware(
    "jwt",
    audience="https://api.example.com/mcp",  # The expected audience for the JWT
    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",
    audience="https://api.example.com/mcp",
    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,
    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", 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}