For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
Set up Auth0
Configure Auth0 as an OAuth identity provider for MCP authentication with agentgateway.
Secure your Model Context Protocol (MCP) servers with OAuth 2.0 authentication by using agentgateway and Auth0 as the identity provider.
About this guide
In this guide, you configure the agentgateway proxy to protect a static MCP server with MCP auth by using Auth0 as the authorization server. Agentgateway includes a native Auth0 provider that adapts to Auth0’s OAuth behavior. When you set provider: Auth0, agentgateway serves Auth0’s RFC 8414 authorization server metadata to MCP clients and appends your API identifier to Auth0’s authorization endpoint as an audience query parameter.
The audience parameter matters. Auth0 does not support RFC 8707 resource indicators, which MCP clients use to request a token for a specific resource. Without the parameter, Auth0 issues an opaque access token that agentgateway cannot validate as a JWT.
For more information about MCP auth, see the About MCP auth page.
Before you begin
- Set up an agentgateway proxy.
- Follow the steps to set up an MCP server with a fetch tool.
- Install the experimental channel Gateway API.
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.0/experimental-install.yaml
Set up Auth0
Create an API and an application in Auth0, and collect the values that agentgateway needs.
Make sure that you have access to an Auth0 tenant. If you do not have one, you can create a free tenant.
In the Auth0 Dashboard, go to Applications > APIs and click Create API. Enter a name such as
agentgateway MCP, and set the Identifier to the resource URL that your MCP clients request, such ashttps://mcp.example.com/mcp. The identifier becomes theaudclaim of the tokens that Auth0 issues.On the API’s Settings tab, enable Add Permissions in the Access Token. Then, on the API’s Permissions tab, define the permissions that your MCP server enforces, such as
read:tools, and grant them to the users or applications that need access. You use this permission in the authorization rule that you configure later.Go to Applications > Applications and click Create Application. Choose Native for local MCP clients, or Single Page Application for browser-based clients. Both are public clients that use PKCE, which is what MCP clients require.
On the application’s Settings tab, note the Domain and the Client ID. Under Application URIs, add the callback URLs of the MCP clients that you plan to connect.
Save the values as environment variables.
export AUTH0_DOMAIN=<your-tenant>.us.auth0.com export AUTH0_CLIENT_ID=<your-application-client-id> export AUTH0_AUDIENCE=https://mcp.example.com/mcpVariable Description AUTH0_DOMAINYour Auth0 tenant domain, without a scheme or trailing slash, such as dev-abc123.us.auth0.com. Copy it from the application’s Settings tab.AUTH0_CLIENT_IDThe Client ID of the application that you created. AUTH0_AUDIENCEThe Identifier of the API that you created. Auth0 sets the audclaim of its access tokens to this value.
Create the JWKS backend
Create an AgentgatewayBackend that points to your Auth0 tenant, and a BackendTLSPolicy that originates a TLS connection to it. The JWT authentication policy uses this backend to fetch Auth0’s public keys for token signature validation.
Create an AgentgatewayBackend for your Auth0 tenant.
kubectl apply -f- <<EOF apiVersion: agentgateway.dev/v1alpha1 kind: AgentgatewayBackend metadata: name: auth0-jwks spec: static: host: ${AUTH0_DOMAIN} port: 443 EOFCreate a BackendTLSPolicy that originates a TLS connection to the
auth0-jwksbackend by using well-known trusted CA certificates.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: auth0-jwks spec: targetRefs: - name: auth0-jwks kind: AgentgatewayBackend group: agentgateway.dev validation: hostname: ${AUTH0_DOMAIN} wellKnownCACertificates: System EOF
Configure MCP auth
With your MCP backend configured, create an AgentgatewayPolicy that enforces Auth0 authentication and authorization for the MCP backend.
Create an AgentgatewayPolicy with the
Auth0provider. The policy validates tokens that Auth0 issues and uses a Common Expression Language (CEL) rule to require theread:toolspermission.kubectl apply -f - <<EOF apiVersion: agentgateway.dev/v1alpha1 kind: AgentgatewayPolicy metadata: name: mcp-auth0-authn spec: # Target the HTTPRoute to apply authentication at the route level targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: mcp traffic: jwtAuthentication: mode: Strict providers: # Auth0 issuers include a trailing slash - issuer: "https://${AUTH0_DOMAIN}/" audiences: - "${AUTH0_AUDIENCE}" jwks: remote: backendRef: name: auth0-jwks kind: AgentgatewayBackend group: agentgateway.dev port: 443 jwksPath: "/.well-known/jwks.json" mcp: # Use the native Auth0 provider to append the audience query parameter provider: Auth0 # Short-circuit Dynamic Client Registration with a pre-registered client clientId: "${AUTH0_CLIENT_ID}" resourceMetadata: resource: http://localhost:8080/mcp scopesSupported: - openid - profile bearerMethodsSupported: - header # Allow only tokens that carry the read:tools permission authorization: action: Allow policy: matchExpressions: - '"read:tools" in jwt.permissions' EOFReview the following table to understand this configuration. For more information about the
traffic.jwtAuthenticationfield, see the API docs.Setting Description providers[].issuerThe Auth0 token issuer URL, including the trailing slash. This value must match the issclaim in the token.providers[].audiencesThe Identifier of your Auth0 API. This value must match the audclaim in the token. Agentgateway also sends the first audience to Auth0 as theaudiencequery parameter.providers[].jwks.remote.backendRefThe auth0-jwksbackend that points to your Auth0 tenant.providers[].jwks.remote.jwksPathThe path to Auth0’s JWKS endpoint. Auth0 serves keys at /.well-known/jwks.json.mcp.providerThe identity provider. Set to Auth0to append theaudiencequery parameter to Auth0’s authorization endpoint.mcp.clientIdThe Client ID of your Auth0 application. Agentgateway answers Dynamic Client Registration requests with this value instead of proxying them to Auth0. mcp.resourceMetadataMCP OAuth resource metadata for discovery. Includes the resource identifier, supported scopes, and bearer token methods. authorization.policy.matchExpressionsCEL rules that authorize the claims in the verified JWT. This example requires the read:toolspermission that you defined on your Auth0 API. Requests that present a valid token without that permission are denied with a 403 HTTP response code.Note
Setting
clientIdis recommended for Auth0. Auth0 supports Dynamic Client Registration, but only when you enable Dynamic Application Registration in your tenant settings. Because agentgateway passes through Auth0’s own registration endpoint rather than proxying it, MCP clients register directly with Auth0. Pre-registering a client withclientIdavoids that dependency.Verify that the policy was accepted.
kubectl get AgentgatewayPolicy mcp-auth0-authn -o yamlIn the
statussection, confirm that theAcceptedandAttachedconditions areTrue.Update the HTTPRoute that routes incoming traffic to the MCP server to include the OAuth discovery paths. This way, the agentgateway proxy can serve the resource and authorization server metadata during the MCP auth flow.
kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mcp spec: parentRefs: - group: gateway.networking.k8s.io kind: Gateway name: agentgateway-proxy namespace: agentgateway-system rules: - filters: # Enable CORS for browser-based MCP clients - type: CORS cors: allowCredentials: true allowHeaders: - Origin - Authorization - Content-Type allowMethods: - "*" allowOrigins: - "*" exposeHeaders: - Origin - Mcp-Session-Id maxAge: 86400 backendRefs: - group: agentgateway.dev kind: AgentgatewayBackend name: mcp-backend matches: # Main MCP endpoint to connect to the MCP server - path: type: PathPrefix value: /mcp # Path to access resource server metadata - path: type: PathPrefix value: /.well-known/oauth-protected-resource/mcp # Path to access authorization server metadata - path: type: PathPrefix value: /.well-known/oauth-authorization-server/mcp EOF
Verify MCP auth
Get the address of the agentgateway proxy.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n agentgateway-system agentgateway-proxy \ -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo "Gateway address: $INGRESS_GW_ADDRESS"Send an unauthenticated request to the MCP endpoint. Verify that the request is rejected with a 401 HTTP response code and a
WWW-Authenticateheader that points MCP clients to the protected resource metadata.curl -i http://$INGRESS_GW_ADDRESS:80/mcp -X POST \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}},"id":1}'Example output:
HTTP/1.1 401 Unauthorized www-authenticate: Bearer resource_metadata="http://localhost:8080/.well-known/oauth-protected-resource/mcp"Verify that the gateway serves the protected resource metadata.
curl -s http://$INGRESS_GW_ADDRESS:80/.well-known/oauth-protected-resource/mcp | jqExample output:
{ "resource": "http://localhost:8080/mcp", "authorization_servers": ["http://localhost:8080/mcp"], "mcp_protocol_version": "2025-06-18", "resource_type": "mcp-server", "bearer_methods_supported": ["header"], "scopes_supported": ["openid", "profile"] }Verify that the gateway serves Auth0’s authorization server metadata, and that the
audiencequery parameter is appended to the authorization endpoint.curl -s http://$INGRESS_GW_ADDRESS:80/.well-known/oauth-authorization-server/mcp \ | jq '{issuer, jwks_uri, authorization_endpoint, registration_endpoint}'Example output. Note the
?audience=parameter that agentgateway appended, and thatregistration_endpointis Auth0’s own endpoint rather than a gateway-proxied one.{ "issuer": "https://your-tenant.us.auth0.com/", "jwks_uri": "https://your-tenant.us.auth0.com/.well-known/jwks.json", "authorization_endpoint": "https://your-tenant.us.auth0.com/authorize?audience=https://mcp.example.com/mcp", "registration_endpoint": "https://your-tenant.us.auth0.com/oidc/register" }
Connect an MCP client
Point your MCP client at the gateway’s MCP endpoint, such as http://localhost:8080/mcp. The client discovers the authorization server through the gateway and redirects the user to Auth0 to log in and consent.
Permission-based authorization
The policy that you created gates the MCP endpoint on the read:tools permission, which Auth0 puts in the permissions claim of the access token when you enable Add Permissions in the Access Token on the API’s Settings tab. Authentication alone is not enough: any caller that Auth0 issues a token to for your API passes JWT validation, including machine-to-machine clients that authorize themselves rather than a user. The authorization rule denies those tokens with a 403 HTTP response code.
Because MCP authentication runs at the route level, every claim in the verified token is also available to other route-level policies, such as rate limiting and transformations. For more information about the rules that you can write, see Authorization.
To authorize individual tools instead of the whole MCP endpoint, use an MCP authorization policy. For more information, see Tool access.
Clean up
You can remove the resources that you created in this guide.kubectl delete AgentgatewayPolicy mcp-auth0-authn
kubectl delete backendtlspolicy auth0-jwks
kubectl delete AgentgatewayBackend auth0-jwks