Control access or route traffic based on verified claims in a JSON web token (JWT). To learn more about JWTs, see the JWT Overview.

About MCP auth

In this guide, you learn how to configure your agentgateway proxy to validate JWT tokens that are provided in an Authorization header. You then authorize access to specific MCP tools based on specific claims in the JWT.

The following diagram shows the components that are involved when performing JWT validation and authorization with MCP servers:

sequenceDiagram
    autonumber
    Client->>+Agentgateway: Send request with JWT
    Agentgateway->>Agentgateway: Validate JWT token
    Agentgateway->>Agentgateway: Authorize access to MCP server
    Agentgateway->>+MCP: Forward request
  1. The MCP client, such as the MCP inspector tool, sends a request to the agentgateway proxy with the JWT token in the Authorization header.
  2. The agentgateway validates the JWT with the JWKS server that you define in a glooJWT policy in the GlooTrafficPolicy resource. This policy is applied to the agentgateway proxy.
  3. If the GlooTrafficPolicy further defines RBAC rules, such as to only grant access for JWT tokens with certain claims, agentgateway validates these claims and either grants or denies access.
  4. If successfully validated and authorized, the agentgateway proxy forwards the request to the MCP backend.

Before you begin

  1. Set up an agentgateway proxy.
  2. Follow the steps to connect to the remote GitHub MCP server via HTTPS.

Validate JWT tokens

You can configure your agentgateway proxy to validate JWT tokens that are sent by an MCP client in an Authorization header.

  1. Create a GlooTrafficPolicy with your JWT validation rules and apply it to the agentgateway proxy that you created before you began. In this example, you use an inline, local JSON Web Key Set (JWKS) to verify the JWT.

      kubectl apply -f- <<EOF
    apiVersion: gloo.solo.io/v1alpha1
    kind: GlooTrafficPolicy
    metadata:
      name: jwt
      namespace: gloo-system
    spec:
      targetRefs:
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: agentgateway
      glooJWT:
        beforeExtAuth:
          providers:
            selfminted:
              issuer: solo.io
              jwks:
                local:
                  key: '{"keys":[{"kty":"RSA","kid":"solo-public-key-001","use":"sig","alg":"RS256","n":"AOfIaJMUm7564sWWNHaXt_hS8H0O1Ew59-nRqruMQosfQqa7tWne5lL3m9sMAkfa3Twx0LMN_7QqRDoztvV3Wa_JwbMzb9afWE-IfKIuDqkvog6s-xGIFNhtDGBTuL8YAQYtwCF7l49SMv-GqyLe-nO9yJW-6wIGoOqImZrCxjxXFzF6mTMOBpIODFj0LUZ54QQuDcD1Nue2LMLsUvGa7V1ZHsYuGvUqzvXFBXMmMS2OzGir9ckpUhrUeHDCGFpEM4IQnu-9U8TbAJxKE5Zp8Nikefr2ISIG2Hk1K2rBAc_HwoPeWAcAWUAR5tWHAxx-UXClSZQ9TMFK850gQGenUp8","e":"AQAB"}]}'
    EOF
      

    Review the following table to understand this configuration. For more information, see the API docs or the JWT guide for more examples.

    FieldDescription
    issuerThe principal that issued the JWT, usually a URL or an email address. If specified, the iss field in the JWT of the incoming request must match this field, or else the request is denied. If omitted, the iss field in the JWT is not checked.
    jwksThe JSON Web Key Set (JWKS) to use to verify the JWT. In this example, a local JWKS is provided inline. To use JWTs with Solo Enterprise for agentgateway, make sure that the JWTs return Key ID (kid) and expiration date (exp) values in the JWT header.
  2. Save the JWT tokens for the users Alice and Bob. You can optionally create other JWT tokens by using the JWT generator tool. Note that to use JWTs with agentgateway proxies, make sure that the JWTs return Key ID (kid) and expiration date (exp) values in the JWT header.

    1. Save the JWT token for Alice. Alice works in the dev team.

        eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImFsaWNlIiwidGVhbSI6ImRldiIsImV4cCI6MjA3NDI3NDg4NCwibGxtcyI6eyJvcGVuYWkiOlsiZ3B0LTMuNS10dXJibyJdfX0.il5Rjsad65jpQR_pyRzBdEKFSj-ERmBf4K2VksvGvswWVv4n79lYERslr4KCECuiz9y_T-xUiQ9IkhW3YHzl5zo1kajhhIg7Nhnl1AvAqODbnF6wYpLRk0Npna_2T6lK3Yj54qQGi6vXG3IMRpo1_o2DrbdlKx2k_WFegCoQyyYazb4z3ZXfWvTiWqQDJA5wWcM3-jKzAWfNM8zgZWa-1BeAHDvpLcfWtuXEGSjkdCW0FQJOTjgIEqACnnXb2Jio0tWgelh9hDPILI-tvanj3iKCjpf3uF6g8QWSBNoVFfu7F1jJgj5Aj1sX8AV-CQVu2aQx3EHRZ1mL_3w3qSRWPw
        
    2. Save the JWT token for Bob. Bob works in the ops team.

        eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImJvYiIsInRlYW0iOiJvcHMiLCJleHAiOjIwNzQyNzQ5NTQsImxsbXMiOnsibWlzdHJhbGFpIjpbIm1pc3RyYWwtbGFyZ2UtbGF0ZXN0Il19fQ.GF_uyLpZSTT1DIvJeO_eish1WDjMaS4BQSifGQhqPRLjzu3nXtPkaBRjceAmJi9gKZYAzkT25MIrT42ZIe3bHilrd1yqittTPWrrM4sWDDeldnGsfU07DWJHyboNapYR-KZGImSmOYshJlzm1tT_Bjt3-RK3OBzYi90_wl0dyAl9D7wwDCzOD4MRGFpoMrws_OgVrcZQKcadvIsH8figPwN4mK1U_1mxuL08RWTu92xBcezEO4CdBaFTUbkYN66Y2vKSTyPCxg3fLtg1mvlzU1-Wgm2xZIiPiarQHt6Uq7v9ftgzwdUBQM1AYLvUVhCN6XkkR9OU3p0OXiqEDjAxcg
        
  3. Get the agentgateway address.

  4. From the terminal, run the MCP Inspector command. Then, the MCP Inspector opens in your browser. If the MCP inspector tool does not open automatically, run mcp-inspector.

      npx modelcontextprotocol/inspector#0.17.5
      
  5. From the MCP Inspector menu, try to connect to your agentgateway address as follows:

    • Transport Type: Select Streamable HTTP.
    • URL: Enter the agentgateway address, port, and the /mcp-github path. If your agentgateway proxy is exposed with a LoadBalancer server, use http://<lb-address>:8080/mcp. In local test setups where you port-forwarded the agentgateway proxy on your local machine, use http://localhost:8080/mcp-github.
    • Click Connect.

    Verify that the connection fails with an error message similar to the following, because no valid JWT was provided from the MCP inspector tool (MCP client) to the agentgateway proxy.
      Connection Error - Check if your MCP server is running and proxy token is correct
      

  6. Check the agentgateway proxy logs and verify that you see 403 authentication failure log entries.

      kubectl logs deploy/agentgateway -n gloo-system
      

    Example output:

      request gateway=default/agentgateway listener=http route=default/mcp src.addr=127.0.0.1:59068
    http.method=POST http.host=localhost http.path=/mcp http.version=HTTP/1.1 http.status=403
    error=authentication failure: no bearer token found duration=0ms
      
  7. Go back to the MCP Inspector tool and expand the Authentication section. Enter the following details in the API Token Authentication card:

    • Header Name: Enter Authorization.

    • Bearer Token: Enter the JWT token for Alice.

        eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImFsaWNlIiwidGVhbSI6ImRldiIsImV4cCI6MjA3NDI3NDg4NCwibGxtcyI6eyJvcGVuYWkiOlsiZ3B0LTMuNS10dXJibyJdfX0.il5Rjsad65jpQR_pyRzBdEKFSj-ERmBf4K2VksvGvswWVv4n79lYERslr4KCECuiz9y_T-xUiQ9IkhW3YHzl5zo1kajhhIg7Nhnl1AvAqODbnF6wYpLRk0Npna_2T6lK3Yj54qQGi6vXG3IMRpo1_o2DrbdlKx2k_WFegCoQyyYazb4z3ZXfWvTiWqQDJA5wWcM3-jKzAWfNM8zgZWa-1BeAHDvpLcfWtuXEGSjkdCW0FQJOTjgIEqACnnXb2Jio0tWgelh9hDPILI-tvanj3iKCjpf3uF6g8QWSBNoVFfu7F1jJgj5Aj1sX8AV-CQVu2aQx3EHRZ1mL_3w3qSRWPw
        
    • Click Connect.


    Verify that the connection now succeeds because a valid token was provided in an Authorization header to your agentgateway proxy:

  8. Repeat the previous step with the JWT token for Bob. Verify that you can also connect to your MCP server successfully.

      eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImJvYiIsInRlYW0iOiJvcHMiLCJleHAiOjIwNzQyNzQ5NTQsImxsbXMiOnsibWlzdHJhbGFpIjpbIm1pc3RyYWwtbGFyZ2UtbGF0ZXN0Il19fQ.GF_uyLpZSTT1DIvJeO_eish1WDjMaS4BQSifGQhqPRLjzu3nXtPkaBRjceAmJi9gKZYAzkT25MIrT42ZIe3bHilrd1yqittTPWrrM4sWDDeldnGsfU07DWJHyboNapYR-KZGImSmOYshJlzm1tT_Bjt3-RK3OBzYi90_wl0dyAl9D7wwDCzOD4MRGFpoMrws_OgVrcZQKcadvIsH8figPwN4mK1U_1mxuL08RWTu92xBcezEO4CdBaFTUbkYN66Y2vKSTyPCxg3fLtg1mvlzU1-Wgm2xZIiPiarQHt6Uq7v9ftgzwdUBQM1AYLvUVhCN6XkkR9OU3p0OXiqEDjAxcg
      

  9. Try to enter an invalid JWT token, such as abcdefg. Verify that access to the MCP server is denied, because the JWT token could not be validated by your agentgateway proxy.

Authorize access based on JWT claims

You can limit access to the MCP server based on specific JWT claims with CEL-based RBAC rules.

  1. Update the GlooTrafficPolicy to add your RBAC rules. In the following example, you use a CEL expression to only allow access to the MCP server if the JWT has the sub=alice claim.

      kubectl apply -f- <<EOF
    apiVersion: gloo.solo.io/v1alpha1
    kind: GlooTrafficPolicy
    metadata:
      name: jwt
      namespace: gloo-system
    spec:
      targetRefs:
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: agentgateway
      glooJWT:
        beforeExtAuth:
          providers:
            selfminted:
              issuer: solo.io
              jwks:
                local:
                  key: '{"keys":[{"kty":"RSA","kid":"solo-public-key-001","use":"sig","alg":"RS256","n":"AOfIaJMUm7564sWWNHaXt_hS8H0O1Ew59-nRqruMQosfQqa7tWne5lL3m9sMAkfa3Twx0LMN_7QqRDoztvV3Wa_JwbMzb9afWE-IfKIuDqkvog6s-xGIFNhtDGBTuL8YAQYtwCF7l49SMv-GqyLe-nO9yJW-6wIGoOqImZrCxjxXFzF6mTMOBpIODFj0LUZ54QQuDcD1Nue2LMLsUvGa7V1ZHsYuGvUqzvXFBXMmMS2OzGir9ckpUhrUeHDCGFpEM4IQnu-9U8TbAJxKE5Zp8Nikefr2ISIG2Hk1K2rBAc_HwoPeWAcAWUAR5tWHAxx-UXClSZQ9TMFK850gQGenUp8","e":"AQAB"}]}'
      rbac:
        policy:
          matchExpressions:
            - 'jwt.sub == "alice"'
    EOF
      
  2. Go back to the MCP inspector tool and expand the Authentication section. Enter the following details in the API Token Authentication card:

    • Header Name: Enter Authorization.
    • Bearer Token: Enter the JWT token for Bob.
        eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImJvYiIsInRlYW0iOiJvcHMiLCJleHAiOjIwNzQyNzQ5NTQsImxsbXMiOnsibWlzdHJhbGFpIjpbIm1pc3RyYWwtbGFyZ2UtbGF0ZXN0Il19fQ.GF_uyLpZSTT1DIvJeO_eish1WDjMaS4BQSifGQhqPRLjzu3nXtPkaBRjceAmJi9gKZYAzkT25MIrT42ZIe3bHilrd1yqittTPWrrM4sWDDeldnGsfU07DWJHyboNapYR-KZGImSmOYshJlzm1tT_Bjt3-RK3OBzYi90_wl0dyAl9D7wwDCzOD4MRGFpoMrws_OgVrcZQKcadvIsH8figPwN4mK1U_1mxuL08RWTu92xBcezEO4CdBaFTUbkYN66Y2vKSTyPCxg3fLtg1mvlzU1-Wgm2xZIiPiarQHt6Uq7v9ftgzwdUBQM1AYLvUVhCN6XkkR9OU3p0OXiqEDjAxcg
        
    • Click Connect.

    Verify that the connection fails with an error message similar to the following, because Bob’s JWT token does not have the sub=alice claim.

      Connection Error - Check if your MCP server is running and proxy token is correct
      

  3. Repeat the previous step with the JWT token for Alice. Verify that you can successfully connect to the MCP server, because the token has the sub=alice claim.

      eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImFsaWNlIiwidGVhbSI6ImRldiIsImV4cCI6MjA3NDI3NDg4NCwibGxtcyI6eyJvcGVuYWkiOlsiZ3B0LTMuNS10dXJibyJdfX0.il5Rjsad65jpQR_pyRzBdEKFSj-ERmBf4K2VksvGvswWVv4n79lYERslr4KCECuiz9y_T-xUiQ9IkhW3YHzl5zo1kajhhIg7Nhnl1AvAqODbnF6wYpLRk0Npna_2T6lK3Yj54qQGi6vXG3IMRpo1_o2DrbdlKx2k_WFegCoQyyYazb4z3ZXfWvTiWqQDJA5wWcM3-jKzAWfNM8zgZWa-1BeAHDvpLcfWtuXEGSjkdCW0FQJOTjgIEqACnnXb2Jio0tWgelh9hDPILI-tvanj3iKCjpf3uF6g8QWSBNoVFfu7F1jJgj5Aj1sX8AV-CQVu2aQx3EHRZ1mL_3w3qSRWPw
      

Next

Explore how to control access to tools with RBAC policies.

Cleanup

You can remove the resources that you created in this guide.
  kubectl delete Backend github-mcp-backend -n gloo-system
kubectl delete BackendTLSPolicy github-mcp-backend-tls -n gloo-system
kubectl delete HTTPRoute mcp-github -n gloo-system
kubectl delete GlooTrafficPolicy jwt -n gloo-system