Skip to content

JWT authorization

Secure agentgateway with JWT authentication and fine-grained access control on Kubernetes

Secure your agentgateway LLM endpoints with JWT authentication using TrafficPolicy on Kubernetes.

What you’ll build

In this tutorial, you will:

  1. Set up a local Kubernetes cluster with agentgateway and an LLM backend
  2. Create a TrafficPolicy with JWT authentication
  3. Test that unauthenticated requests are rejected
  4. Test that authenticated requests with a valid JWT are allowed

Before you begin

Make sure you have the following tools installed:

For detailed installation instructions, see the LLM Gateway tutorial.


Step 1: Create a kind cluster

kind create cluster --name agentgateway

Step 2: Install agentgateway

# Gateway API CRDs
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.0/standard-install.yaml

# agentgateway CRDs
helm upgrade -i --create-namespace \
  --namespace agentgateway-system \
  --version v agentgateway-crds oci://cr.agentgateway.dev/charts/agentgateway-crds

# Control plane
helm upgrade -i -n agentgateway-system agentgateway oci://cr.agentgateway.dev/charts/agentgateway \
  --version v

Step 3: Create a Gateway

kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: agentgateway-proxy
  namespace: agentgateway-system
spec:
  gatewayClassName: agentgateway
  listeners:
  - protocol: HTTP
    port: 80
    name: http
    allowedRoutes:
      namespaces:
        from: All
EOF

Wait for the proxy:

kubectl get deployment agentgateway-proxy -n agentgateway-system

Step 4: Set up an LLM backend

Set your API key and create the secret and backend:

export OPENAI_API_KEY=<insert your API key>

kubectl apply -f- <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: openai-secret
  namespace: agentgateway-system
type: Opaque
stringData:
  Authorization: $OPENAI_API_KEY
---
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
  name: openai
  namespace: agentgateway-system
spec:
  ai:
    provider:
      openai:
        model: gpt-4.1-nano
  policies:
    auth:
      secretRef:
        name: openai-secret
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: openai
  namespace: agentgateway-system
spec:
  parentRefs:
    - name: agentgateway-proxy
      namespace: agentgateway-system
  rules:
    - backendRefs:
      - name: openai
        namespace: agentgateway-system
        group: agentgateway.dev
        kind: AgentgatewayBackend
EOF

Step 5: Download the test JWT keys

For this tutorial, use pre-generated test keys from the agentgateway repository:

# Download the JWKS public key
curl -sL https://raw.githubusercontent.com/agentgateway/agentgateway/main/manifests/jwt/pub-key -o pub-key

# Download a pre-generated test JWT token
curl -sL https://raw.githubusercontent.com/agentgateway/agentgateway/main/manifests/jwt/example1.key -o test-token.jwt
These are test keys only. For production, generate your own keys using tools like step-cli.

The test token contains these claims:

{
  "iss": "solo.io",
  "sub": "alice",
  "exp": 1900650294
}

Step 6: Create a JWT TrafficPolicy

Create a TrafficPolicy that enforces JWT authentication on the Gateway. Requests without a valid JWT will be rejected.

# Read the JWKS into a variable
JWKS=$(cat pub-key)

kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TrafficPolicy
metadata:
  name: jwt-auth
  namespace: agentgateway-system
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: Gateway
      name: agentgateway-proxy
  traffic:
    jwtAuthentication:
      mode: Strict
      providers:
        - issuer: solo.io
          jwks:
            inline: '$JWKS'
      authorization:
        action: Allow
        policy:
          matchExpressions:
            - 'jwt.sub == "alice"'
EOF

This policy:

  • Requires a valid JWT on every request (mode: Strict)
  • Validates the token against the provided JWKS public key
  • Authorizes only tokens where sub is alice

Step 7: Test the JWT authentication

Set up port-forwarding:

kubectl port-forward deployment/agentgateway-proxy -n agentgateway-system 8080:80 &

Test without a token (should fail)

curl -s http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-4.1-nano", "messages": [{"role": "user", "content": "Hello"}]}'

You should receive a 401 Unauthorized response.

Test with a valid token (should succeed)

curl -s http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $(cat test-token.jwt)" \
  -d '{"model": "gpt-4.1-nano", "messages": [{"role": "user", "content": "Hello! What is JWT?"}]}' | jq

You should receive a successful response from OpenAI.


Authorization rules

The matchExpressions field uses CEL (Common Expression Language) for fine-grained access control:

# Allow only a specific user
matchExpressions:
  - 'jwt.sub == "alice"'

# Allow by email domain
matchExpressions:
  - 'jwt.email.endsWith("@company.com")'

# Allow by role claim
matchExpressions:
  - '"admin" in jwt.roles'

Cleanup

kill %1 2>/dev/null
kind delete cluster --name agentgateway

Next steps

JWT Reference

Complete JWT configuration options

Tool Access Control

Control MCP tool access with JWT claims

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/.