> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/agentgateway/agentgateway/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Reference for authentication policies — mcpAuthentication, jwtAuth, apiKey, and basicAuth.

The `mcpAuthentication` policy validates incoming Bearer tokens from MCP clients against a configured OAuth 2.0 / OIDC authorization server. When enabled, Agentgateway enforces token validity before allowing any MCP traffic and optionally serves [OAuth 2.0 Protected Resource Metadata](https://datatracker.ietf.org/doc/html/rfc9728) at `/.well-known/oauth-protected-resource/<path>`.

## Configuration location

`mcpAuthentication` is set under `binds[].listeners[].routes[].policies`:

```yaml theme={null}
binds:
- port: 3000
  listeners:
  - routes:
    - policies:
        mcpAuthentication:
          issuer: https://auth.example.com
          audiences:
          - https://gateway.example.com/mcp
          jwks:
            url: https://auth.example.com/.well-known/jwks.json
```

## Fields

<ParamField body="issuer" type="string" required>
  The expected `iss` (issuer) claim in the JWT. Must exactly match the issuer URL of your authorization server.

  ```yaml theme={null}
  issuer: https://auth.example.com
  ```
</ParamField>

<ParamField body="audiences" type="string[]" required>
  A list of accepted `aud` (audience) values. The token must contain at least one of these values.

  ```yaml theme={null}
  audiences:
  - https://gateway.example.com/mcp
  ```
</ParamField>

<ParamField body="jwks" type="object" required>
  Source of the JSON Web Key Set (JWKS) used to verify token signatures. Exactly one of `file` or `url` must be set.

  <Expandable title="jwks fields">
    <ParamField body="jwks.url" type="string">
      HTTP(S) URL of the JWKS endpoint. Agentgateway fetches and caches keys from this URL.

      ```yaml theme={null}
      jwks:
        url: https://auth.example.com/.well-known/jwks.json
      ```
    </ParamField>

    <ParamField body="jwks.file" type="string">
      Path to a local JWKS file on disk. The path is relative to the directory from which the Agentgateway binary runs (not relative to the config file).

      ```yaml theme={null}
      jwks:
        file: ./keys/jwks.json
      ```
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="mode" type="string">
  Token enforcement mode. When set to `strict`, Agentgateway rejects requests that do not carry a valid Bearer token. When omitted or set to a permissive value, tokens are validated when present but not required.

  ```yaml theme={null}
  mode: strict
  ```
</ParamField>

<ParamField body="provider" type="object">
  Optional provider hint for non-spec-compliant authorization servers. When set, Agentgateway activates a compatibility adapter that adjusts `/.well-known/oauth-authorization-server` responses. Exactly one of `auth0` or `keycloak` must be specified.

  <Expandable title="provider options">
    <ParamField body="provider.auth0" type="object">
      Enables the Auth0 compatibility adapter. Set to an empty object `{}`.

      ```yaml theme={null}
      provider:
        auth0: {}
      ```
    </ParamField>

    <ParamField body="provider.keycloak" type="object">
      Enables the Keycloak compatibility adapter. Set to an empty object `{}`.

      ```yaml theme={null}
      provider:
        keycloak: {}
      ```
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="resourceMetadata" type="object">
  Configures the [OAuth 2.0 Protected Resource Metadata](https://datatracker.ietf.org/doc/html/rfc9728) document served at `/.well-known/oauth-protected-resource/<path>`. MCP clients use this to discover the correct authorization server.

  <Expandable title="resourceMetadata fields">
    <ParamField body="resourceMetadata.resource" type="string" required>
      The canonical URI of the protected resource. Typically the full URL of the MCP endpoint.

      ```yaml theme={null}
      resource: https://gateway.example.com/mcp
      ```
    </ParamField>

    <ParamField body="resourceMetadata.scopesSupported" type="string[]">
      OAuth 2.0 scopes supported by this resource.

      ```yaml theme={null}
      scopesSupported:
      - read:all
      - offline_access
      ```
    </ParamField>

    <ParamField body="resourceMetadata.bearerMethodsSupported" type="string[]">
      Accepted methods for submitting Bearer tokens. Valid values: `header`, `body`, `query`.

      ```yaml theme={null}
      bearerMethodsSupported:
      - header
      - body
      - query
      ```
    </ParamField>

    <ParamField body="resourceMetadata.resourceDocumentation" type="string">
      URI pointing to human-readable documentation for the resource.
    </ParamField>

    <ParamField body="resourceMetadata.resourcePolicyUri" type="string">
      URI pointing to a policy document for the resource.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="jwtValidationOptions" type="object">
  Fine-grained control over which RFC 7519 registered claims must be present in the token before validation proceeds.

  <Expandable title="jwtValidationOptions fields">
    <ParamField body="jwtValidationOptions.requiredClaims" type="string[]" default="[&#x22;exp&#x22;]">
      Claims that must be present in the token payload. Only the following values are recognized: `exp`, `nbf`, `aud`, `iss`, `sub`. Other claims (including `iat` and `jti`) are silently ignored.

      This setting controls **presence** only. Standard claims such as `exp` and `nbf` are still validated for value correctness (e.g., expiry is always enforced when `exp` is present) regardless of this list.

      Use an empty list `[]` to require no specific claims:

      ```yaml theme={null}
      jwtValidationOptions:
        requiredClaims: []
      ```

      Default: `["exp"]`
    </ParamField>
  </Expandable>
</ParamField>

## Examples

<AccordionGroup>
  <Accordion title="Standard OIDC provider">
    ```yaml theme={null}
    mcpAuthentication:
      mode: strict
      issuer: https://auth.example.com
      audiences:
      - https://gateway.example.com/stdio/mcp
      jwks:
        url: https://auth.example.com/.well-known/jwks.json
      resourceMetadata:
        resource: https://gateway.example.com/stdio/mcp
        scopesSupported:
        - read:all
        bearerMethodsSupported:
        - header
        - body
        - query
    ```
  </Accordion>

  <Accordion title="Keycloak provider">
    ```yaml theme={null}
    mcpAuthentication:
      issuer: http://localhost:7080/realms/mcp
      audiences:
      - mcp_proxy
      jwks:
        url: http://localhost:7080/realms/mcp/protocol/openid-connect/certs
      provider:
        keycloak: {}
      resourceMetadata:
        resource: http://localhost:3000/keycloak/mcp
        scopesSupported:
        - profile
        - offline_access
        - openid
        bearerMethodsSupported:
        - header
        - body
        - query
    ```
  </Accordion>

  <Accordion title="Auth0 provider">
    ```yaml theme={null}
    mcpAuthentication:
      issuer: https://dev-example.eu.auth0.com
      audiences:
      - urn:agent-gateway
      jwks:
        url: https://dev-example.eu.auth0.com/.well-known/jwks.json
      provider:
        auth0: {}
      resourceMetadata:
        resource: http://localhost:3000/auth0/mcp
        scopesSupported:
        - profile
        - openid
        bearerMethodsSupported:
        - header
    ```
  </Accordion>

  <Accordion title="Local JWKS file with strict validation">
    ```yaml theme={null}
    mcpAuthentication:
      mode: strict
      issuer: agentgateway.dev
      audiences:
      - test.agentgateway.dev
      jwks:
        file: ./manifests/jwt/pub-key
      jwtValidationOptions:
        requiredClaims:
        - exp
        - sub
    ```
  </Accordion>
</AccordionGroup>

<Note>
  When `resourceMetadata` is configured, Agentgateway automatically registers `/.well-known/oauth-protected-resource/<path>` and `/.well-known/oauth-authorization-server/<path>` endpoints. Include these paths in your route `matches` so the gateway serves them correctly.
</Note>

<Warning>
  The `exp` claim is **always** checked when it is present in a token, regardless of whether `requiredClaims` includes `"exp"`. Including `"exp"` in `requiredClaims` only means the token will be rejected if the claim is absent, not that expiry checking is added.
</Warning>

***

## jwtAuth

The `jwtAuth` policy provides generic JWT validation for any route — not limited to MCP. Unlike `mcpAuthentication`, it does not expose OAuth resource metadata endpoints. Use it for standard API authentication and as the authentication layer alongside `mcpAuthorization`.

**Configuration location:** `binds[].listeners[].routes[].policies.jwtAuth`

The policy supports two forms:

<Tabs>
  <Tab title="Single provider (shorthand)">
    ```yaml theme={null}
    policies:
      jwtAuth:
        issuer: agentgateway.dev
        audiences:
        - test.agentgateway.dev
        jwks:
          file: ./manifests/jwt/pub-key
    ```
  </Tab>

  <Tab title="Multiple providers">
    ```yaml theme={null}
    policies:
      jwtAuth:
        mode: strict
        providers:
        - issuer: https://auth1.example.com
          audiences:
          - https://api.example.com
          jwks:
            url: https://auth1.example.com/.well-known/jwks.json
        - issuer: https://auth2.example.com
          audiences:
          - https://api.example.com
          jwks:
            url: https://auth2.example.com/.well-known/jwks.json
    ```
  </Tab>
</Tabs>

### Fields

<ParamField body="mode" type="string">
  Enforcement mode. When set to `strict`, requests without a valid token are rejected.
</ParamField>

<ParamField body="issuer" type="string">
  Expected `iss` claim. Used in the single-provider shorthand form.
</ParamField>

<ParamField body="audiences" type="string[]">
  Accepted `aud` claim values. Used in the single-provider shorthand form.
</ParamField>

<ParamField body="jwks" type="object">
  JWKS source. One of `file` (path on disk, relative to binary working directory) or `url` (HTTP endpoint).
</ParamField>

<ParamField body="providers" type="object[]">
  List of JWT providers for multi-provider configurations. Each provider has `issuer`, `audiences`, `jwks`, and `jwtValidationOptions` fields identical to the single-provider shorthand.
</ParamField>

<ParamField body="jwtValidationOptions.requiredClaims" type="string[]" default="[&#x22;exp&#x22;]">
  Claims that must be present in the token. Recognized values: `exp`, `nbf`, `aud`, `iss`, `sub`. Defaults to `["exp"]`.
</ParamField>

Once a JWT is validated, its claims are available as `jwt.<claim>` in CEL expressions used by `mcpAuthorization` and `authorization` policies.

***

## apiKey

The `apiKey` policy authenticates requests using static API keys passed in the `Authorization: Bearer` header or `x-api-key` header.

**Configuration location:** `binds[].listeners[].routes[].policies.apiKey`

```yaml theme={null}
policies:
  apiKey:
    keys:
    - key: my-secret-api-key
      metadata:
        user: alice
    - key: another-secret-key
      metadata:
        user: bob
    mode: strict
```

### Fields

<ParamField body="apiKey.keys" type="object[]" required>
  List of valid API keys.

  <Expandable title="key fields">
    <ParamField body="key" type="string" required>
      The API key value.
    </ParamField>

    <ParamField body="metadata" type="object">
      Arbitrary metadata associated with this key, available as `apiKey.<field>` in CEL expressions.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="apiKey.mode" type="string">
  Enforcement mode. When set to `strict`, requests without a valid key are rejected.
</ParamField>

API key metadata is available in CEL as `apiKey.key` and any custom metadata fields under `apiKey.<field>`.

***

## basicAuth

The `basicAuth` policy authenticates requests using HTTP Basic Authentication validated against an htpasswd file.

**Configuration location:** `binds[].listeners[].routes[].policies.basicAuth`

```yaml theme={null}
policies:
  basicAuth:
    htpasswd:
      file: ./htpasswd
    realm: "My Gateway"
    mode: strict
```

### Fields

<ParamField body="basicAuth.htpasswd" type="object" required>
  Source of the htpasswd credentials.

  <Expandable title="htpasswd fields">
    <ParamField body="htpasswd.file" type="string">
      Path to an htpasswd file on disk.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="basicAuth.realm" type="string">
  Realm name sent in the `WWW-Authenticate` header when authentication fails.
</ParamField>

<ParamField body="basicAuth.mode" type="string">
  Enforcement mode. When set to `strict`, unauthenticated requests are rejected with `401`.
</ParamField>

Authenticated credentials are available in CEL as `basicAuth.username`.
