APIs and MCP

A browser provider, a JWT provider and an MCP protected resource.

This example separates the browser session from machine tokens and exposes one MCP service with its protected-resource metadata.

File

{
  "authProviders": [
    {
      "id": "company", "type": "oidc",
      "issuer": "https://auth.example.com/t/company",
      "clientId": "gate-one",
      "clientSecretEnv": "MYCOMPANY_OIDC_SECRET",
      "loginBaseUrl": "https://login.example.com",
      "cookieDomain": "example.com",
      "sessionKeyEnv": "MYCOMPANY_SESSION_KEY"
    },
    {
      "id": "company-api", "type": "jwt",
      "issuer": "https://auth.example.com/t/company",
      "jwksUrl": "https://auth.example.com/t/company/jwks.json",
      "audience": "https://api.example.com"
    }
  ],
  "defaultAuthProvider": "company",
  "routes": [
    {
      "host": "app.example.com", "path": "/*", "frontend": true,
      "backend": "http://app:8080", "auth": {}
    },
    {
      "host": "api.example.com", "path": "/v1/*", "backend": "http://api:8080",
      "auth": {
        "provider": "company-api",
        "identity": { "scopes": ["read:things"] }
      }
    },
    {
      "host": "mcp.example.com", "path": "/mcp", "backend": "http://mcp:8080",
      "auth": { "provider": "company-api" },
      "mcp": {
        "enabled": true, "path": "/mcp", "name": "things",
        "resource": "https://mcp.example.com", "scope": "mcp-tools",
        "operations": [{ "name": "list_things", "operationId": "listThings" }]
      }
    }
  ]
}

Try the API route

TOKEN="$(curl -s -X POST https://auth.example.com/t/company/token \
  -d grant_type=client_credentials \
  -d client_id=... -d client_secret=... | jq -r .access_token)"

curl -i https://api.example.com/v1/things \
  -H "Authorization: Bearer $TOKEN"

A token without read:things gets a 403 from the gateway; the request never reaches the API. An anonymous call gets a 401.

Try the MCP route

curl -s https://mcp.example.com/.well-known/oauth-protected-resource | jq
curl -s https://mcp.example.com/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

The metadata advertises the resource, the scope and the authorization server. The token audience must match resource.

Note
  • A jwt provider never hosts a login page and never issues tokens.

  • auth.when is technical and evaluated before authentication; auth.identity is evaluated after it.

  • The JWT provider validates the token signature and aud; it does not validate the upstream IdP directly.

  • mcp.operations and mcp.upstream are mutually exclusive. Use upstream to proxy an existing MCP server instead of declaring REST operations.