ZuploZuplo
LoginSign Up
  • Documentation
  • API Reference
Introduction
Getting Started
    Develop using the Portal
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingMCP - Quick start
    Develop Locally
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth
Concepts
Development
Policies
Handlers
API Keys
MCP Server
MCP Gateway
    IntroductionBetaQuickstartQuickstart (Local Dev)How it works
    Connect MCP clients
    Authentication
      OverviewUpstream OAuthConnect an upstream OAuth provider
      Identity providers
        Auth0Amazon CognitoClerkMicrosoft EntraGoogleKeycloakLogtoOktaOneLoginPingOneWorkOSGeneric OIDC
      Manual OAuth testing
    Configuration
    Observability
    ReferenceTroubleshooting
AI Gateway
Developer Portal
Monetization
Deploying & Source Control
Observability
Networking & Infrastructure
Account Management
Programming API
Build with AI
Zuplo CLI
Migration Guides
Platform LimitsSecuritySupportTrust & ComplianceChangelog
powered by Zudoku
Identity providers

Configuring Auth0

The MCP Gateway can use Auth0 as the identity provider behind its downstream OAuth flow. The mcp-auth0-oauth-inbound policy is an Auth0-friendly wrapper around the generic mcp-oauth-inbound policy: provide your Auth0 domain, a client ID, and a client secret, and the policy derives the OIDC issuer, JWKS URL, and Auth0 authorize and token URLs for you.

This guide walks through the Auth0 dashboard setup, then shows how to wire the policy into your gateway project. Read the authentication overview first for the two-layer model and the role each policy plays.

This guide assumes you have a working Auth0 tenant. The Auth0 MCP client registration guide is the authoritative source for Auth0-side configuration.

Most projects only need three options: auth0Domain, clientId, and clientSecret. audience, scope, and the TTL options are all optional.

auth0Domain is a bare hostname, not a URL. Use my-tenant.us.auth0.com, not https://my-tenant.us.auth0.com/.

Set up the Auth0 tenant

The MCP Gateway acts as an OAuth 2.1 authorization server in front of Auth0. Auth0 handles browser login and identity; the gateway issues its own access tokens that bind to MCP routes. The Auth0 application you create represents the gateway's identity against Auth0, not the MCP client.

Create an Auth0 application

  1. In the Auth0 Dashboard, open Applications > Applications and click Create Application.
  2. Set a name (for example, Zuplo MCP Gateway).
  3. Choose Regular Web Application as the application type and click Create.
  4. On the Settings tab, note the Domain, Client ID, and Client Secret. You'll wire these into the policy in the next section.

Configure callback and origin URLs

The gateway completes browser login by redirecting back to its own /oauth/callback endpoint, so Auth0 needs that URL on its allow-list.

On the same Settings tab:

  1. Set Allowed Callback URLs to your gateway's https://<gateway-host>/oauth/callback. For local development against zuplo dev, add http://localhost:9000/oauth/callback as well.
  2. Set Allowed Web Origins to the gateway origin https://<gateway-host> (plus http://localhost:9000 for local dev).
  3. Save changes.

Optional: Set an audience

If you want Auth0 to issue identity-bound API access tokens (for example, to validate Auth0-issued tokens against a specific resource server), create an API under Applications > APIs with an identifier like https://gateway.example.com and pass that identifier as the audience option on the policy. When omitted, Auth0 acts only as the browser identity layer and the gateway alone owns the OAuth grant the MCP client receives.

Connections and dynamic client registration

The downstream OAuth flow only requires Auth0 to authenticate the user and return an ID token. CIMD and DCR on Auth0's side concern the upstream MCP server's trust of clients, not the gateway's trust of Auth0. If you also configure Auth0 itself as an upstream MCP authorization provider (rare), follow Auth0's own guide for enabling CIMD or enabling DCR.

Wire the policy into the gateway

Add the policy to config/policies.json:

Code
{ "name": "auth0-managed-oauth", "policyType": "mcp-auth0-oauth-inbound", "handler": { "module": "$import(@zuplo/runtime/mcp-gateway)", "export": "McpAuth0OAuthInboundPolicy", "options": { "auth0Domain": "$env(AUTH0_DOMAIN)", "clientId": "$env(AUTH0_CLIENT_ID)", "clientSecret": "$env(AUTH0_CLIENT_SECRET)" } } }

Set the three environment variables in your Zuplo project's environment configuration. AUTH0_DOMAIN is the bare hostname; the secret values belong in the project secret store.

Attach the policy to each MCP route in config/routes.oas.json:

Code
{ "paths": { "/mcp/linear": { "get,post": { "operationId": "linear-mcp-server", "x-zuplo-route": { "corsPolicy": "none", "handler": { "module": "$import(@zuplo/runtime/mcp-gateway)", "export": "McpProxyHandler", "options": { "rewritePattern": "https://mcp.linear.app/mcp", }, }, "policies": { "inbound": ["auth0-managed-oauth", "mcp-token-exchange-linear"], }, }, }, }, }, }

Finally, register the gateway plugin in modules/zuplo.runtime.ts so the runtime registers the OAuth endpoints automatically:

Code
import { RuntimeExtensions } from "@zuplo/runtime"; import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway"; export function runtimeInit(runtime: RuntimeExtensions) { runtime.addPlugin(new McpGatewayPlugin()); }

One MCP OAuth policy serves every MCP route in the project — there's no need to declare it more than once. Attaching the same policy by name to each route is the canonical pattern.

Full options reference

mcp-auth0-oauth-inbound has three required options and a few optional overrides. The complete schema is documented on the policy reference page; the fields you'll touch most often are:

OptionRequiredDefaultNotes
auth0Domainyes—Bare hostname (my-tenant.us.auth0.com). No scheme, must contain a dot.
clientIdyes—Auth0 application client ID.
clientSecretyes—Auth0 application client secret. Use $env(...) to source from a secret.
audiencenounsetOptional Auth0 API identifier. Sent as the ?audience= parameter to Auth0's /authorize.
scopenoopenid profile emailOIDC scopes requested during browser login.
gateway.accessTokenTtlSecondsno900Gateway-issued access token lifetime.
gateway.refreshTokenTtlSecondsnolong-livedGateway-issued refresh token lifetime. Override only if you need to shorten sessions.
gateway.cimdEnablednotrueAdvertise CIMD support in AS metadata.
browserLoginOverrides.sessionTtlSecondsno28800Browser session cookie lifetime (8 hours).
browserLoginOverrides.stateTtlSecondsno900Browser-login state record lifetime.
browserLoginOverrides.remoteTimeoutMsno10000Outbound timeout to Auth0 (token exchange, JWKS fetch).

Test the configuration

The fastest sanity check is to try connecting an MCP client:

  1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
  2. Add a remote MCP server pointing at one of your /mcp/{slug} routes on the gateway.
  3. The client should redirect you to Auth0's login page. After login, the gateway's consent screen renders. Approve it.
  4. The client receives an access token and can call tools/list.

If something fails partway through, walk the flow manually using the manual OAuth testing guide — it exercises every endpoint with curl so you can see the raw responses.

Common issues

  • "Invalid Auth0 domain" at boot. The auth0Domain value includes a scheme prefix or doesn't contain a dot. Use my-tenant.us.auth0.com.
  • Browser login redirects but the callback fails. The https://<gateway-host>/oauth/callback URL isn't on the Allowed Callback URLs list for the Auth0 application.
  • Token endpoint returns invalid_audience. The MCP client is reusing a token bound to a different route. Each gateway-issued token binds to one operationId; the client must obtain a separate token per route.
  • Issuer in AS metadata is wrong. The gateway derives its issuer from the incoming request origin. Check that your custom domain or proxy forwards the correct Host or X-Forwarded-Host header. See Troubleshooting.
  • MCP client can't discover the AS. Confirm the mcp-auth0-oauth-inbound policy is attached to the route in routes.oas.json and that the McpGatewayPlugin is registered in modules/zuplo.runtime.ts. The internal OAuth endpoints register only when both are present.

Related

  • Authentication overview
  • mcp-auth0-oauth-inbound policy reference
  • Configuring Okta or any other OIDC IdP
  • Per-user OAuth to upstream MCP servers
Edit this page
Last modified on May 27, 2026
Connect an upstream OAuth providerAmazon Cognito
On this page
  • Set up the Auth0 tenant
    • Create an Auth0 application
    • Configure callback and origin URLs
    • Optional: Set an audience
    • Connections and dynamic client registration
  • Wire the policy into the gateway
  • Full options reference
  • Test the configuration
  • Common issues
  • Related
JSON
JSON
TypeScript