ZuploZuplo
LoginStart for Free
  • Documentation
  • API Reference
Getting Started
    Develop in the portal
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
    Develop locally with the CLI
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
Concepts
API Management
AI Gateway
MCP Gateway
    OverviewQuickstartQuickstart (Local Dev)How it works
    Connect MCP clients
    Authentication
    Cross App Access
    Configuration
    Policies
      Overview
      Authorization
        Generic OAuthAuth0 OAuthClerk OAuthAmazon Cognito OAuthMicrosoft Entra OAuthGoogle OAuthKeycloak OAuthLogto OAuthOkta OAuthOneLogin OAuthPingOne OAuthWorkOS OAuthToken Exchange
      Security & Validation
    Observability
    ReferenceServer RegistryTroubleshooting
MCP Server
Developer Portal
Development
Deploying & Source Control
Analytics
Observability
Networking & Infrastructure
Account Management
Programming API
Build with AI
Zuplo CLI
Migration Guides
Platform LimitsVersion Support PolicySecuritySupportTrust & ComplianceChangelog
powered by Zudoku
Authorization

MCP Keycloak OAuth Policy

MCP Gateway Policy

This policy is for use with the MCP Gateway. See the MCP Gateway documentation to learn how to proxy and secure MCP servers with Zuplo.

Use the MCP Keycloak OAuth policy to protect an MCP virtual server with gateway-issued OAuth tokens while delegating browser login to a Keycloak realm.

Configuration

The configuration shows how to configure the policy in the 'policies.json' document.

Code
{ "name": "my-mcp-keycloak-oauth-inbound-policy", "policyType": "mcp-keycloak-oauth-inbound", "handler": { "export": "McpKeycloakOAuthInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "browserLoginOverrides": { "pkce": "none", "remoteTimeoutMs": 10000, "sessionTtlSeconds": 28800, "stateTtlSeconds": 900 }, "clientId": "$env(KEYCLOAK_CLIENT_ID)", "clientSecret": "$env(KEYCLOAK_CLIENT_SECRET)", "gateway": { "accessTokenTtlSeconds": 900, "cimdEnabled": true, "refreshTokenTtlSeconds": 2592000 }, "keycloakBaseUrl": "https://sso.example.com", "realm": "master", "scope": "openid profile email" } } }

Policy Configuration

  • name <string> - The name of your policy instance. This is used as a reference in your routes.
  • policyType <string> - The identifier of the policy. This is used by the Zuplo UI. Value should be mcp-keycloak-oauth-inbound.
  • handler.export <string> - The name of the exported type. Value should be McpKeycloakOAuthInboundPolicy.
  • handler.module <string> - The module containing the policy. Value should be $import(@zuplo/runtime).
  • handler.options <object> - The options for this policy. See Policy Options below.

Policy Options

The options for this policy are specified below. All properties are optional unless specifically marked as required.

  • keycloakBaseUrl (required) <string> - The absolute URL for the Keycloak server root. Do not include /realms/{realm}; set the realm option separately.
  • realm (required) <string> - The Keycloak realm name.
  • clientId (required) <string> - The Keycloak OIDC client_id registered for the gateway's browser login flow.
  • clientSecret (required) <string> - The Keycloak OIDC client_secret. Use $env(...) to source from a secret environment variable.
  • scope <string> - OIDC scopes requested during browser login. Defaults to "openid profile email".
  • gateway <object> - Gateway-side OAuth token settings. The gateway issuer and advertised URLs are derived from the incoming request origin.
    • accessTokenTtlSeconds <integer> - Lifetime of access tokens issued by /oauth/token. Defaults to 900.
    • refreshTokenTtlSeconds <integer> - Lifetime of refresh tokens issued by /oauth/token. Defaults to 2592000.
    • cimdEnabled <boolean> - Whether to advertise client_id_metadata_document_supported in AS metadata. Defaults to true.
  • idJag <undefined> - Optional Identity Assertion JWT Authorization Grant (ID-JAG / XAA) support for the gateway token endpoint.
  • browserLoginOverrides <object> - Optional overrides for the derived browser-login settings.
    • remoteTimeoutMs <integer> - No description available. Defaults to 10000.
    • stateTtlSeconds <integer> - No description available. Defaults to 900.
    • sessionTtlSeconds <integer> - No description available. Defaults to 28800.
    • pkce <string> - Whether to send S256 PKCE on the federated browser-login authorization request and replay the verifier at the token exchange. Defaults to "none". Set to "S256" when the identity provider mandates PKCE on the authorization-code flow. Allowed values are S256, none. Defaults to "none".

Using the Policy

MCP Keycloak OAuth

The MCP Keycloak OAuth policy is a provider-specific wrapper around the generic MCP OAuth inbound policy. It keeps the gateway OAuth behavior the same, but lets you configure Keycloak with the values an administrator normally has:

  • keycloakBaseUrl
  • realm
  • clientId
  • clientSecret

The policy derives the Keycloak realm issuer, JWKS URL, authorization endpoint, and token endpoint from Keycloak's OpenID Connect endpoint layout.

Code
{ "name": "keycloak-oauth", "policyType": "mcp-keycloak-oauth-inbound", "handler": { "export": "McpKeycloakOAuthInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "keycloakBaseUrl": "https://sso.example.com", "realm": "customer-portal", "clientId": "$env(KEYCLOAK_CLIENT_ID)", "clientSecret": "$env(KEYCLOAK_CLIENT_SECRET)" } } }

If your Keycloak deployment uses a path prefix, include it in keycloakBaseUrl:

Code
{ "keycloakBaseUrl": "https://sso.example.com/auth", "realm": "customer-portal", "clientId": "$env(KEYCLOAK_CLIENT_ID)", "clientSecret": "$env(KEYCLOAK_CLIENT_SECRET)" }

Do not include /realms/{realm} in keycloakBaseUrl; set realm separately.

Read more about how policies work

Edit this page
Last modified on September 2, 2026
Google OAuthLogto OAuth
On this page
  • Configuration
    • Policy Configuration
    • Policy Options
  • Using the Policy
JSON
JSON
JSON