Skip to main content

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 and audience validation

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.

Always Validate Scopes

In OAuth 2.0, scopes are the primary mechanism for permission control. A valid token with the correct audience does NOT guarantee the user has permission to perform an action — authorization servers may issue tokens with an empty or limited scope.

Always use requiredScopes to enforce that the token contains the necessary permissions for each operation. Never assume a valid token implies full access.

Here's an example of the basic scope and audience validation:

import express from 'express';
import { MCPAuth } from 'mcp-auth';

const app = express();
const mcpAuth = new MCPAuth({
  /* ... */
});
const bearerAuth = mcpAuth.bearerAuth('jwt', {
  resource: 'https://api.example.com', // Specify which resource this endpoint belongs to
  audience: 'https://api.example.com', // Enable audience validation for security
  requiredScopes: ['read', 'write'],
});

app.use('/mcp', bearerAuth, (req, res) => {
  // Now `req.auth` contains the auth info
  console.log(req.auth);
});

In the example above:

  • The audience parameter validates the aud claim in the JWT to ensure the token was specifically issued for your MCP server resource. The audience value should typically match your resource identifier.
  • The requiredScopes parameter specifies that the JWT requires the read and write scopes. If the token does not contain all of these scopes, an error will be thrown.

Provide custom options to the JWT verification

You can also provide custom options to the underlying JWT verification library. In Node.js SDK, we use jose library for JWT verification. You can provide the following options:

  • jwtVerify: Options for the JWT verification process (jwtVerify function from jose).
  • remoteJwtSet: Options for fetching the remote JWT set (createRemoteJWKSet function from jose).
const bearerAuth = mcpAuth.bearerAuth('jwt', {
  resource: 'https://api.example.com',
  audience: 'https://api.example.com',
  requiredScopes: ['read', 'write'],
  jwtVerify: {
    clockTolerance: 60, // Allow a 60 seconds clock skew
  },
  remoteJwtSet: {
    timeoutDuration: 10 * 1000, // 10 seconds timeout for remote JWT set fetching
  },
});

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.

const bearerAuth = mcpAuth.bearerAuth(
  async (token) => {
    // Implement your custom verification logic here
    const info = await verifyToken(token);
    if (!info) {
      throw new MCPAuthJwtVerificationError('jwt_verification_failed');
    }
    return info; // Return the auth info object
  },
  {
    resource: 'https://api.example.com',
    audience: 'https://api.example.com', // Enable audience validation for security
    requiredScopes: ['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.

const app = express();
app.use(
  mcpAuth.bearerAuth('jwt', {
    resource: 'https://api.example.com',
    audience: 'https://api.example.com', // Enable audience validation for security
    requiredScopes: ['read', 'write'],
  })
);

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:

// `authInfo` will be carried from the `req.auth` object
server.registerTool(
  'whoami',
  {
    description: 'Returns the current user info',
    inputSchema: {},
  },
  ({ authInfo }) => {
    console.log(`Authenticated user: ${authInfo.subject}`);
    return { subject: authInfo.subject };
  }
);