# Egress JWT Authentication to MCP Servers

Teleport sends a JWT token signed with Teleport's authority with each request to a target MCP server in a `Teleport-Jwt-Assertion` header.

You can use the JWT token to get information about the authenticated Teleport user, its roles, and its traits. This allows you to:

- Map Teleport identity/roles/traits onto the identity/roles/traits of your web application.
- Trust Teleport identity to automatically sign in users into your application.

## Introduction to JWTs

JSON Web Token (JWT) is an open standard that defines a secure way to transfer information between parties as a JSON Object.

For an in-depth explanation please visit <https://jwt.io/introduction/>.

Teleport JWTs include three sections:

- Header
- Payload
- Signature

### Header

*Example Header*

```
{
  "alg": "RS256",
  "typ": "JWT"
}

```

### Payload

*Example Payload*

```
{
  "aud": [
    "http://127.0.0.1:34679"
  ],
  "iss": "aws",
  "nbf": 1603835795,
  "sub": "alice",
  // Teleport user name.
  "username": "alice"
  // Teleport user roles.
  "roles": [
    "admin"
  ],
  // Teleport user traits.
  "traits": {
    "logins": [
      "root",
      "ubuntu",
      "ec2-user"
    ]
  },
  // Teleport identity expiration.
  "exp": 1603943800,
}

```

The JWT will be sent with the header: `Teleport-Jwt-Assertion`.

*Example Teleport JWT Assertion*

```
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaHR0cDovLzEyNy4wLjAuMTozNDY3OSJdLCJleHAiOjE2MDM5NDM4MDAsImlzcyI6ImF3cyIsIm5iZiI6MTYwMzgzNTc5NSwicm9sZXMiOlsiYWRtaW4iXSwic3ViIjoiYmVuYXJlbnQiLCJ1c2VybmFtZSI6ImJlbmFyZW50In0.PZGUyFfhEWl22EDniWRLmKAjb3fL0D4cTmkxEfb-Q30hVMzVhka5WB8AUsPsLPVhTzsQ6Nkk1DnXHdz6oxrqDDfumuRrDnpJpjiXj_l0D3bExrchN61enzBHxSD13VkRIqP1V6l4i8yt8kXDIBWc-QejLTodA_GtczkDfnnpuAfaxIbD7jEwF27KI4kZu7uES9LMu2iCLdV9ZqarA-6HeDhXPA37OJ3P6eVQzYpgaOBYro5brEiVpuJLr1yA0gncmR4FqmhCpCj-KmHi2vmjmJAuuHId6HZoEZJjC9IAsNlrSA4GHH9j82o7FF1F4J2s38bRy3wZv46MT8X8-QBSpg

```

## Classic JWTs

Classic JWTs are Teleport-generated JWTs issued by Teleport JWT CA and validated using Teleport's JWKS endpoint at `.well-known/jwks.json`. These tokens are sent in the `Teleport-Jwt-Assertion` header by default, but can be injected into any header.

### Inject Classic JWTs

You can inject a JWT token into any header using [headers passthrough](https://goteleport.com/docs/enroll-resources/application-access/protect-apps/connecting-apps.md#headers-passthrough) configuration and the `{{internal.jwt}}` template variable. This variable will be replaced with JWT token signed by Teleport JWT CA containing user identity information like described above.

For example:

```
- name: "my-mcp-server"
  uri: mcp+http://localhost:4321
  rewrite:
    headers:
    - "Authorization: Bearer {{internal.jwt}}"

```

### Validate Classic JWTs

Teleport provides a JSON Web Key Set (`jwks`) endpoint to verify that the JWT can be trusted. This endpoint is `https://[cluster-name]/.well-known/jwks.json`:

*Example jwks.json*

```
{
  "keys": [
    {
      "kty": "RSA",
      "n": "xk-0VSVZY76QGqeN9TD-FJp32s8jZrpsalnRoFwlZ_JwPbbd5-_bPKcz8o2tv1eJS0Ll6ePxRCyK68Jz2UC4V4RiYaqJCRq_qVpDQMB1sQ7p9M-8qvT82FJ-Rv-W4RNe3xRmBSFDYdXaFm51Uk8OIYfv-oZ0kGptKpkNY390aJOzjHPH2MqSvhk9Xn8GwM8kEbpSllavdJCRPCeNVGJXiSCsWrOA_wsv_jqBP6g3UOA9GnI8R6HR14OxV3C184vb3NxIqxtrW0C4W6UtSbMDcKcNCgajq2l56pHO8In5GoPCrHqlo379LE5QqpXeeHj8uqcjeGdxXTuPrRq1AuBpvQ",
      "e": "AQAB",
      "alg": "RS256"
    }
  ]
}

```

See the example Go program used to validate Teleport's JWT tokens on our [GitHub](https://github.com/gravitational/teleport/blob/v18.7.3/examples/mcp-servers/).

## ID Tokens (OIDC)

ID tokens are Teleport-generated JWTs issued by Teleport OIDC CA and validated using Teleport’s OIDC discovery document at `.well-known/openid-configuration`.

### Inject ID Tokens

You can inject an ID token into any header using headers passthrough configuration and the `{{internal.id_token}}` template variable. This variable will be replaced with ID token signed by Teleport OIDC CA containing user identity information like described above.

For example:

```
- name: "my-mcp-server"
  uri: mcp+http://localhost:4321
  rewrite:
    headers:
    - "Authorization: Bearer {{internal.id_token}}"

```

### Validate ID Tokens

Teleport provides an OIDC discovery endpoint to verify that the ID tokens can be trusted. This endpoint is `https://[cluster-name]/.well-known/openid-configuration`:

```
{
  "issuer": "https://teleport.example.com",
  "jwks_uri": "https://teleport.example.com/.well-known/jwks-oidc",
  "claims": [ "iss", "sub", "obo", "aud", "jti", "iat", "exp", "nbf" ],
  "id_token_signing_alg_values_supported": [ "RS256" ],
  "response_types_supported": [ "id_token" ],
  "scopes_supported": [ "openid" ],
  "subject_types_supported": [ "public" ]
}

```

In ID tokens, the issuer claim `iss` follows the OIDC specification in the form `https://[cluster-name]`. All other claims remain the same as in classic JWTs, with the audience claim `aud` set to the Teleport application URI.

See the [example](https://goteleport.com/docs/enroll-resources/mcp-access/integration-guides/aws-bedrock-gateway.md) for configuring an Amazon Bedrock AgentCore MCP Gateway to accept Teleport-generated ID tokens.

## Troubleshooting

By default, Teleport includes a user's roles and traits in the JWT generated for application access, and the `Teleport-Jwt-Assertion` header is sent along with every request that Teleport makes to an upstream MCP server.

If your MCP server doesn't care about these values, or you are encountering an error due to exceeding the size limit of HTTP headers, you can configure Teleport to omit this information from the token.

```
- name: "dashboard"
  uri: mcp+http://localhost:4321
  rewrite:
    # Specify whether to include roles or traits in the JWT.
    # Options:
    # - roles-and-traits: include both roles and traits
    # - roles: include only roles
    # - traits: include only traits
    # - none: exclude both roles and traits from the JWT token
    # Default: roles-and-traits
    jwt_claims: roles-and-traits
    headers:
    # Inject header with Teleport-signed JWT token.
    - "Authorization: Bearer {{internal.jwt}}"

```
