Skip to content
agentgateway has joined the Agentic AI FoundationLearn more

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Page as Markdown

JWT auth

Verified Code examples on this page have been automatically tested and verified.

Set up JWT authentication with an identity provider like Keycloak.

Secure your applications with JSON Web Token (JWT) authentication by using the agentgateway proxy and an identity provider like Keycloak. To learn more about JWT auth, see About JWT authentication.

Before you begin

  1. Set up an agentgateway proxy.
  2. Install the httpbin sample app.

Install Keycloak

You might want to test how to restrict access to your applications to authenticated users, such as with external auth or JWT policies. You can install Keycloak in your cluster as an OpenID Connect (OIDC) provider.

The following steps install Keycloak in your cluster, and configure two user credentials as follows.

Install and configure Keycloak:

  1. Create a namespace for your Keycloak deployment.
    kubectl create namespace keycloak
  2. Create the Keycloak deployment.
    kubectl -n keycloak apply -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/oidc/keycloak.yaml
  3. Wait for the Keycloak rollout to finish.
    kubectl -n keycloak rollout status deploy/keycloak
  1. Set the Keycloak endpoint details from the load balancer service. If you are running locally in kind and need a local IP address for the load balancer service, consider using cloud-provider-kind.

    export ENDPOINT_KEYCLOAK=$(kubectl -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].ip}{.status.loadBalancer.ingress[0].hostname}'):8080
    export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK} | cut -d: -f1)
    export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK} | cut -d: -f2)
    export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK}
    echo $KEYCLOAK_URL
  2. Set the Keycloak admin token. If you see a parsing error, try running the curl command by itself. You might notice that your internet provider or network rules are blocking the requests. If so, you can update your security settings or change the network so that the request can be processed.

    export KEYCLOAK_TOKEN=$(curl -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token)
    echo $KEYCLOAK_TOKEN
  3. Use the admin token to configure Keycloak with the two users for testing purposes. If you get a 401 Unauthorized error, run the previous command and try again.

    # Create initial token to register the client
    read -r client token <<<$(curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"expiration": 0, "count": 1}' $KEYCLOAK_URL/admin/realms/master/clients-initial-access | jq -r '[.id, .token] | @tsv')
    export KEYCLOAK_CLIENT=${client}
    echo $KEYCLOAK_CLIENT
    
    # Register the client
    read -r id secret <<<$(curl -k -X POST -d "{ \"clientId\": \"${KEYCLOAK_CLIENT}\" }" -H "Content-Type:application/json" -H "Authorization: bearer ${token}" ${KEYCLOAK_URL}/realms/master/clients-registrations/default| jq -r '[.id, .secret] | @tsv')
    export KEYCLOAK_SECRET=${secret}
    echo $KEYCLOAK_SECRET
    
    # Add allowed redirect URIs
    curl -k -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X PUT -H "Content-Type: application/json" -d '{"serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["*"]}' $KEYCLOAK_URL/admin/realms/master/clients/${id}
    
    # Add the group attribute in the JWT token returned by Keycloak
    curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": {"claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true"}}' $KEYCLOAK_URL/admin/realms/master/clients/${id}/protocol-mappers/models
    
    # Create first user
    curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"username": "user1", "email": "[email protected]", "firstName": "Alice", "lastName": "Doe", "enabled": true, "attributes": {"group": "users"}, "credentials": [{"type": "password", "value": "password", "temporary": false}]}' $KEYCLOAK_URL/admin/realms/master/users
    
    # Create second user
    curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"username": "user2", "email": "[email protected]", "firstName": "Bob", "lastName": "Doe", "enabled": true, "attributes": {"group": "users"}, "credentials": [{"type": "password", "value": "password", "temporary": false}]}' $KEYCLOAK_URL/admin/realms/master/users
    
    # Remove the trusted-hosts client registration policies (testing-purpose only)
    trusted_hosts=$(curl -v -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" \
     "${KEYCLOAK_URL}/admin/realms/master/components?type=org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" \
     | jq -r '
      if type=="array" then
        .[] | select(.providerId=="trusted-hosts") | .id
      else
        empty
     end
    ')
    
    curl -X DELETE \
      -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" \
      "${KEYCLOAK_URL}/admin/realms/master/components/${trusted_hosts}"
    
    # Remove the allowed-client-templates client registration policies (testing-purpose only)
    
    allowed_client_templates=$(curl -v \
     -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" \
     "${KEYCLOAK_URL}/admin/realms/master/components?type=org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" \
     | jq -r '
     .[]
      | select(.providerId=="allowed-client-templates" and .subType=="anonymous")
      | .id
    ')
    
    curl -X DELETE \
      -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" \
      "${KEYCLOAK_URL}/admin/realms/master/components/${allowed_client_templates}"
  4. Open the Keycloak frontend.

    open $KEYCLOAK_URL
  5. Log in to the admin console, and enter admin as the username and admin as your password.

  6. In the Keycloak admin console, go to Users, and verify that the users that created earlier are displayed. You might need to click on View all users to see them.

  7. In the Keycloak admin console, go to Clients, and verify that you can see a client ID that equals the output of $KEYCLOAK_CLIENT.

Retrieve JWKS path and issuer URL

You might integrate OIDC with your apps. In such cases, you might need particular details from the OIDC provider to fully set up your apps. To use Keycloak for OAuth protection of these apps, you need certain settings and information from Keycloak.

The following instructions assume that you are still logged into the Administration Console from the previous step.

  1. Confirm that you have the following environmental variables set. If not, refer to Step 1: Install Keycloak section.

    echo $KEYCLOAK_URL
  2. Get the issuer and JWKS path. The agentgateway proxy uses these values to validate the JWTs.

    1. From the sidebar menu options, click Realm Settings.
    2. From the General tab, scroll down to the Endpoints section and open the OpenID Endpoint Configuration link. In a new tab, your browser opens to a URL similar to http://$KEYCLOAK_URL:8080/realms/master/.well-known/openid-configuration.
    3. In the OpenID configuration, search for the issuer field. Save the value as an environment variable, such as the following example.
      export KEYCLOAK_ISSUER=$KEYCLOAK_URL/realms/master
    4. In the OpenID configuration, search for the jwks_uri field, and copy the path without the Keycloak URL that you retrieved earlier. For example, the path might be set to /realms/master/protocol/openid-connect/certs.
      export KEYCLOAK_JWKS_PATH=/realms/master/protocol/openid-connect/certs

Set up JWT authentication

Configure an AgentgatewayPolicy to validate JWTs using a remote JWKS endpoint from Keycloak. This approach is recommended for production as it supports automatic key rotation.

  1. Create an AgentgatewayPolicy with JWT authentication configuration.

    kubectl apply -f - <<EOF
    apiVersion: agentgateway.dev/v1alpha1
    kind: AgentgatewayPolicy
    metadata:
      name: jwt-auth-policy
      namespace: agentgateway-system
    spec:
      # Target the Gateway to apply JWT authentication to all routes
      targetRefs:
      - group: gateway.networking.k8s.io
        kind: Gateway
        name: agentgateway-proxy   
      # Configure JWT authentication
      traffic:
        jwtAuthentication:
          # Validation mode - determines how strictly JWTs are validated
          mode: Strict   
          # List of JWT providers (identity providers)
          providers:
          - # Issuer URL - must match the 'iss' claim in JWT tokens
            issuer: "${KEYCLOAK_ISSUER}"
            # JWKS configuration for remote key fetching
            jwks:
              remote:
                # Path to the JWKS endpoint, relative to the backend root
                jwksPath: "${KEYCLOAK_JWKS_PATH}"
                # Cache duration for JWKS keys (reduces load on identity provider)
                cacheDuration: "5m"
                # Reference to the Keycloak service
                backendRef:
                  group: ""
                  kind: Service
                  name: keycloak
                  namespace: keycloak
                  port: 8080
    EOF
    FieldDescriptionExample
    modeValidation mode for JWT authentication. Strict requires a valid JWT for all requests. Optional validates JWTs if present but allows requests without tokens. Permissive is the least strict mode.Strict
    issuerThe issuer URL that must match the iss claim in JWT tokens exactly. Agentgateway rejects tokens from other issuers.http://keycloak:8080/realms/master
    audiencesList of allowed audience values. The JWT’s aud claim must contain at least one of these values. If not specified, any audience is accepted.["my-application"]
    jwks.remote.jwksPathThe path to the JWKS endpoint on the identity provider, relative to the backend root. This endpoint returns the public keys used to verify JWT signatures./realms/master/protocol/openid-connect/certs
    jwks.remote.cacheDurationHow long to cache the JWKS keys locally. This reduces load on the identity provider and improves performance. Keys are automatically refreshed when the cache expires.5m (5 minutes)
    jwks.remote.backendRefReference to the backend that hosts the identity provider. Agentgateway uses this to fetch the JWKS from the identity provider. For an in-cluster provider, reference a Kubernetes Service. For an external provider reached over TLS, reference an AgentgatewayBackend instead. See External identity provider over TLS.Keycloak service
  2. View the details of the policy. Verify that the policy is accepted.

    kubectl get AgentgatewayPolicy jwt-auth-policy -n agentgateway-system -o json | jq '.status'

Verify JWT authentication

Now that JWT authentication is configured, test the setup by obtaining a token from Keycloak and making authenticated requests.

  1. Send a request to the httpbin app without any JWT token. Verify that the request fails with a 401 HTTP response code.

    curl -v "${INGRESS_GW_ADDRESS}:80/headers" -H "host: www.example.com"

    Example output:

    HTTP/1.1 401 Unauthorized
    content-type: text/plain
    response-gateway: response path /headers
    content-length: 45
    date: Mon, 19 Jan 2026 16:07:12 GMT
    
    authentication failure: no bearer token found%  
  2. Get an access token from Keycloak by using the password grant type.

    ACCESS_TOKEN=$(curl -s -X POST "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=password" \
      -d "client_id=${KEYCLOAK_CLIENT}" \
      -d "client_secret=${KEYCLOAK_SECRET}" \
      -d "username=user1" \
      -d "password=password" \
      | jq -r '.access_token')
    
    echo $ACCESS_TOKEN
  3. Repeat the request to the httpbin app. This time, include the JWT token that you received in the previous step. Verify that the request succeeds and you get back a 200 HTTP response code.

    curl -v "${INGRESS_GW_ADDRESS}:80/headers" -H "host: www.example.com" -H "Authorization: Bearer ${ACCESS_TOKEN}"

    Example output:

    ...
    < HTTP/1.1 200 OK
    ...
    {
     "headers": {
       "Accept": [
         "*/*"
       ],
       "Host": [
         "www.example.com"
       ],
       "User-Agent": [
         "curl/8.7.1"
       ]
     }
    }

Other JWT auth examples

Review other common JWT auth configuration examples that you can add to your AgentgatewayPolicy.

Multiple JWT providers

You can configure multiple JWT providers to accept tokens from different identity providers. The following example uses Keycloak and the Auth0 identity providers.


traffic:
  jwtAuthentication:
    mode: Strict
    providers:
    - issuer: "${KEYCLOAK_ISSUER}"
      audiences: ["my-application"]
      jwks:
        remote:
          jwksPath: "${KEYCLOAK_JWKS_PATH}"
          backendRef:
            name: keycloak
            namespace: keycloak
            kind: Service
            port: 8080
    - issuer: "https://auth0.example.com/"
      audiences: ["my-other-application"]
      jwks:
        remote:
          jwksPath: "/.well-known/jwks.json"
          backendRef:
            name: auth0-proxy
            namespace: auth-system
            kind: Service
            port: 443

External identity provider over TLS

When your identity provider runs outside the cluster (for example, Okta, Auth0, or Microsoft Entra ID) and is served over HTTPS, reference an AgentgatewayBackend in the jwks.remote.backendRef instead of a Kubernetes Service. The AgentgatewayBackend sets the upstream host and TLS SNI together, so the JWKS fetch connects to the provider with the correct hostname and certificate.

  1. Create an AgentgatewayBackend for the identity provider. Set static.host to the provider’s public hostname and policies.tls.sni to the same hostname. Because no caCertificateRefs are set, the gateway proxy validates the provider’s certificate against the system trust store.

    kubectl apply -f - <<EOF
    apiVersion: agentgateway.dev/v1alpha1
    kind: AgentgatewayBackend
    metadata:
      name: okta-jwks
      namespace: agentgateway-system
    spec:
      static:
        host: myorg.okta.com
        port: 443
      policies:
        tls:
          sni: myorg.okta.com
    EOF
  2. Create an AgentgatewayPolicy that points jwks.remote.backendRef at the AgentgatewayBackend that you created.

    kubectl apply -f - <<EOF
    apiVersion: agentgateway.dev/v1alpha1
    kind: AgentgatewayPolicy
    metadata:
      name: jwt-auth-policy
      namespace: agentgateway-system
    spec:
      # Target the Gateway to apply JWT authentication to all routes
      targetRefs:
      - group: gateway.networking.k8s.io
        kind: Gateway
        name: agentgateway-proxy
      # Configure JWT authentication
      traffic:
        jwtAuthentication:
          mode: Strict
          providers:
          - issuer: "https://myorg.okta.com/oauth2/default"
            audiences: ["my-application"]
            jwks:
              remote:
                jwksPath: "/oauth2/default/v1/keys"
                cacheDuration: "5m"
                backendRef:
                  group: agentgateway.dev
                  kind: AgentgatewayBackend
                  name: okta-jwks
                  port: 443
    EOF

    Note

    If the AgentgatewayBackend is in a different namespace than the AgentgatewayPolicy, add the namespace field to the backendRef and create a ReferenceGrant that permits the cross-namespace reference.

Inline JWKS

For testing purposes, you can use inline JWKS instead of a remote JWKS endpoint. Note that this setup is not recommended for production as it requires manual key updates.


traffic:
  jwtAuthentication:
    mode: Strict
    providers:
    - issuer: "${KEYCLOAK_ISSUER}"
      audiences: ["my-application"]
      jwks:
        inline: '{"keys":[{"kty":"RSA","kid":"key-id-123","use":"sig","n":"0vx7agoebG...","e":"AQAB"}]}'

Allow missing

By default, the JWT validation mode is set to Strict and allows connections to a backend destination only if a valid JWT was provided as part of the request.

To allow requests, even if no JWT was provided or if the JWT cannot be validated, use the Permissive or Optional modes.

Optional

The JWT is optional. If a JWT is provided during the request, the agentgateway proxy validates it. In the case that the JWT validation fails, the request is denied. However, keep in mind that if no JWT is provided during the request, the request is explicitly allowed.


traffic:
  jwtAuthentication:
    mode: Optional
    providers:
    - issuer: "${KEYCLOAK_ISSUER}"
      audiences: ["my-application"]
      jwks:
        remote:
          jwksPath: "${KEYCLOAK_JWKS_PATH}"
          backendRef:
            name: keycloak
            namespace: keycloak
            kind: Service
            port: 8080

Permissive

Requests are never rejected, even if no or invalid JWTs are provided during the request.


traffic:
  jwtAuthentication:
    mode: Permissive
    providers:
    - issuer: "${KEYCLOAK_ISSUER}"
      audiences: ["my-application"]
      jwks:
        remote:
          jwksPath: "${KEYCLOAK_JWKS_PATH}"
          backendRef:
            name: keycloak
            namespace: keycloak
            kind: Service
            port: 8080

PreRouting phase

By default, JWT authentication is enforced during routing. Use the PreRouting phase to validate JWTs before any routing decision is made. This is useful when you want to enforce authentication for all traffic at the gateway level, regardless of the route.


traffic:
  phase: PreRouting
  jwtAuthentication:
    mode: Strict
    providers:
    - issuer: "${KEYCLOAK_ISSUER}"
      audiences: ["my-application"]
      jwks:
        remote:
          jwksPath: "${KEYCLOAK_JWKS_PATH}"
          cacheDuration: "5m"
          backendRef:
            name: keycloak
            namespace: keycloak
            kind: Service
            port: 8080

Use JWT claims in transformations

After a JWT is validated, its claims are available to CEL expressions through the jwt context variable. You can use these claims in transformations to forward the authenticated user’s identity to your backends, or to route requests based on a claim. See Claim-based routing.

The jwt variable is populated only after the JWT is validated. Keep jwtAuthentication and the transformation on the same AgentgatewayPolicy and phase so that both apply to the same requests. JWT authentication always runs before transformations in the request pipeline, so the claims are available when the transformation evaluates them.

Available JWT claims

Access standard and custom claims from the jwt variable. Registered claims, such as sub, use dot notation. Custom claims whose names contain special characters, such as a URL, require bracket notation.

CEL expressionDescription
jwt.subThe subject (sub) claim, which is usually the user ID.
jwt.issThe issuer (iss) claim.
jwt.audThe audience (aud) claim.
jwt.expThe expiration (exp) time, as a Unix timestamp.
jwt['custom-claim']Any custom claim. Use bracket notation for claim names that contain special characters, such as jwt['https://example.com/tier'].
jwt.rawTokenThe raw bearer token. Redacted by default. Use jwt.rawToken.unredacted() to access the value.

Because the value field of a transformation is a CEL expression, jwt.sub refers to the claim value, not the literal string jwt.sub. To set a header to a fixed string instead, wrap the value in inner single quotes, such as value: "'my-value'". A claim might also be absent from a token, so wrap claim access in default() to provide a fallback and avoid errors, such as default(jwt.role, 'user'). For the full list of context variables and functions, see the CEL reference.

Forward JWT claims to a backend

In this example, you add a transformation to the JWT policy that copies claims from the validated token into request headers before the request is forwarded to the backend. This is a common way to pass the authenticated user’s identity to upstream apps without having them parse the JWT.

  1. Update the jwt-auth-policy to add a transformation that sets request headers from JWT claims. The x-user-role header uses default() to fall back to user when the role claim is absent.

    kubectl apply -f - <<EOF
    apiVersion: agentgateway.dev/v1alpha1
    kind: AgentgatewayPolicy
    metadata:
      name: jwt-auth-policy
      namespace: agentgateway-system
    spec:
      targetRefs:
      - group: gateway.networking.k8s.io
        kind: Gateway
        name: agentgateway-proxy
      traffic:
        jwtAuthentication:
          mode: Strict
          providers:
          - issuer: "${KEYCLOAK_ISSUER}"
            jwks:
              remote:
                jwksPath: "${KEYCLOAK_JWKS_PATH}"
                cacheDuration: "5m"
                backendRef:
                  group: ""
                  kind: Service
                  name: keycloak
                  namespace: keycloak
                  port: 8080
        # Copy JWT claims into request headers for the backend
        transformation:
          request:
            set:
            - name: x-user-id
              value: "jwt.sub"
            - name: x-auth-issuer
              value: "jwt.iss"
            - name: x-user-role
              value: "default(jwt.role, 'user')"
    EOF
  2. Using the ACCESS_TOKEN that you retrieved in Verify JWT authentication, send an authenticated request to the httpbin app. Because httpbin echoes back the headers that it receives, you can verify that the claims were injected.

    curl -s "${INGRESS_GW_ADDRESS}:80/headers" -H "host: www.example.com" -H "Authorization: Bearer ${ACCESS_TOKEN}" | jq '.headers'

    In the response, verify that the X-User-Id, X-Auth-Issuer, and X-User-Role headers contain the values from your JWT claims.

    {
      "Accept": ["*/*"],
      "Host": ["www.example.com"],
      "User-Agent": ["curl/8.7.1"],
      "X-Auth-Issuer": ["http://keycloak:8080/realms/master"],
      "X-User-Id": ["a1b2c3d4-..."],
      "X-User-Role": ["user"]
    }

Claim-based routing

You can route requests to different backends based on a JWT claim, such as sending premium and free-tier users to different services. To do this, use a PreRouting transformation to copy a claim into a request header, then match on that header in your HTTPRoute rules. The PreRouting phase runs the transformation before the gateway makes a routing decision, so the header is available for matching. See PreRouting phase.

Important

This example is illustrative. The following steps show how to derive a routing header from a claim and confirm it is set, but verifying the full premium/free split requires two things that you must configure:

  • Running premium-backend and free-backend Services. Replace them with your own backends, then compare which one handles the request.
  • A token that carries the tier claim. The default Keycloak master-realm token has no tier claim, so every request falls back to free. To exercise the premium path, configure a Keycloak client scope or protocol mapper that adds a tier claim, then request a token that includes tier: premium.
  1. Create or update the jwt-auth-policy to validate the JWT and, in the PreRouting phase, copy a tier claim into an x-user-tier header. Reusing the same policy name replaces the policy from the previous section, so that only one JWT policy targets the Gateway.

    kubectl apply -f - <<EOF
    apiVersion: agentgateway.dev/v1alpha1
    kind: AgentgatewayPolicy
    metadata:
      name: jwt-auth-policy
      namespace: agentgateway-system
    spec:
      targetRefs:
      - group: gateway.networking.k8s.io
        kind: Gateway
        name: agentgateway-proxy
      traffic:
        phase: PreRouting
        jwtAuthentication:
          mode: Strict
          providers:
          - issuer: "${KEYCLOAK_ISSUER}"
            jwks:
              remote:
                jwksPath: "${KEYCLOAK_JWKS_PATH}"
                cacheDuration: "5m"
                backendRef:
                  group: ""
                  kind: Service
                  name: keycloak
                  namespace: keycloak
                  port: 8080
        transformation:
          request:
            set:
            - name: x-user-tier
              value: "default(jwt.tier, 'free')"
    EOF
  2. Before you add routing rules, confirm that the PreRouting transformation derives the x-user-tier header from the JWT claim. Send an authenticated request to the httpbin app, which echoes back the headers that it receives. Because the default Keycloak token has no tier claim, default(jwt.tier, 'free') evaluates to free. For local testing with port-forwarding, use http://localhost:8080/headers instead.

    curl -s "${INGRESS_GW_ADDRESS}:80/headers" -H "host: www.example.com" -H "Authorization: Bearer ${ACCESS_TOKEN}" | jq '.headers'

    In the response, verify that the X-User-Tier header is set to free.

    {
      "Accept": ["*/*"],
      "Host": ["www.example.com"],
      "User-Agent": ["curl/8.7.1"],
      "X-User-Tier": ["free"]
    }
  3. Create an HTTPRoute that routes requests to different backends based on the x-user-tier header. Requests with x-user-tier: premium go to the premium backend, and all other requests fall through to the default backend.

    kubectl apply -f - <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: tier-routing
      namespace: agentgateway-system
    spec:
      parentRefs:
      - name: agentgateway-proxy
      hostnames:
      - www.example.com
      rules:
      # Premium users, matched on the header set from the JWT claim
      - matches:
        - headers:
          - name: x-user-tier
            value: premium
        backendRefs:
        - name: premium-backend
          port: 8080
      # All other users
      - backendRefs:
        - name: free-backend
          port: 8080
    EOF

Cleanup

You can remove the resources that you created in this guide.
kubectl delete AgentgatewayPolicy jwt-auth-policy -n agentgateway-system
kubectl delete httproute tier-routing -n agentgateway-system --ignore-not-found
kubectl delete ns keycloak
Was this page helpful?
Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.