# Validate bearer tokens on a surface

> Create a JWT verification strategy and attach it to a surface's source authentication so only callers with a valid, correctly issued token can reach it.

This guide creates a JWT verification strategy, a reusable configuration naming a trusted issuer and its signing keys, and attaches it to a surface’s JWT bearer source authentication. For how this fits alongside the other authentication methods, see [Security and access control →](/products/affinidi-trust-fabric/agent-stream/concepts/security-and-access-control.md).

A surface authenticating callers only by a shared API key can confirm a caller holds the right secret, but not who they are. A JWT bearer token additionally carries a subject and a full set of claims, such as tenant, role, or department, that downstream OPA policy and audit can act on individually, rather than treating every holder of the key as the same caller.

Use this guide when:

- Your callers already receive OAuth or OIDC access tokens from an identity provider, and you want the surface to validate them directly.

- A policy or audit trail needs the caller’s subject and claims, not just a pass/fail authentication check.

- More than one surface needs to trust the same issuer’s tokens.

You do not need this if a shared API key is sufficient proof of identity for your callers, since a JWT verification strategy is more setup for the same yes/no authentication outcome without additional claim data.

## Prerequisites

- An active LLM Surface.

- Administrator role in the dashboard, to create a JWT verification strategy.

- The issuer’s expected iss claim value, and its JWKS source: a reachable JWKS URL, or the static JWKS JSON if the issuer has no discovery endpoint.

- A valid access token from that issuer, to use in the Confirm section below.

## Steps

Create a JWT verification strategy

In the dashboard’s JWT verification strategy management screen (administrator role required), select Add Strategy and fill in:

| Field | Description |
| Name | A descriptive label, for example Auth0 production. |
| Expected Issuer | The exact iss claim value the token must contain, including a trailing slash if the issuer’s tokens carry one. |
| JWKS Source | Remote URL, with a reachable JWKS URI, or Static Keys, with the JWKS JSON pasted directly. |

Select Create Strategy.

Attach the strategy to the surface

Under SURFACES in the dashboard sidebar, select LLM, open your surface, and open its Caller Context panel. Set the authentication method to JWT Bearer, then select your strategy from the JWT Verification Strategy dropdown.

Restrict accepted audiences, if needed

If your issuer’s tokens carry an aud claim you want to enforce, add one or more values under Accepted Audiences. The token matches if its aud contains any one of them. Leave this empty to skip audience validation, for issuers whose tokens omit aud entirely.

Adjust the token header, if not using a standard bearer header

Token Header defaults to Authorization and Scheme defaults to Bearer, matching a standard Authorization: Bearer <token> header. Change these only if your callers present the token differently.

Save the surface

Select the save icon in the toolbar. The change applies immediately; no restart is required.

## Confirm

Replace <YOUR_APPLIANCE_HOST>, <YOUR_SURFACE_ROUTE>, and <YOUR_JWT_TOKEN> with your surface’s values and a valid token from your issuer.

### Test 1: a valid token returns 200

```bash
curl -k -X POST "https:///v1/chat/completions" \
  -H "Authorization: Bearer " \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      { "role": "user", "content": "Say hello." }
    ]
  }'
```

The -k flag disables TLS certificate verification. Use this for local testing only. Remove it in production.

Expected: 200 OK. The surface validated the token’s signature and issuer, and the request proceeded through the pipeline with the token’s subject and claims available downstream.

### Test 2: a missing token returns 401

Send the same request with the Authorization header removed. Expected: 401 Unauthorized, since no bearer token was presented at all.

## Troubleshooting

| Symptom | Likely cause | Fix |
| Saving the strategy fails when validating the JWKS URI. | The URI is unreachable from the appliance’s network, or resolves to an address the SSRF guard rejects. | Confirm the URI is publicly resolvable, and that it does not point at an internal or cloud-metadata address. |
| A valid token still returns 401. | The token’s iss claim does not match Expected Issuer exactly, including a trailing-slash difference. | Decode the token (for example at jwt.io) and compare its iss claim byte-for-byte against the strategy’s Expected Issuer. |
| A valid token is accepted, but audience checks reject it. | The token’s aud claim does not match any value under Accepted Audiences. | Add the correct audience value, or clear the list to accept any audience. |
| No strategies appear in the JWT Verification Strategy dropdown. | No strategy has been created yet. | Complete the first step above, then return to the surface’s Caller Context panel. |
| The provider itself receives the caller’s raw JWT in its own Authorization header. | Forward caller’s token to the provider (identity pass-through) is enabled separately from source authentication. | By default the JWT bearer credential is stripped before the request is forwarded. If pass-through is not deliberate for this surface, select the surface’s Surface node, select Configure Surface Features, scroll to Identity pass-through, and turn that switch off. |

## Next steps

- [Limit dashboard actions with RBAC roles](/products/affinidi-trust-fabric/agent-stream/how-to-guides/security/limit-dashboard-actions-with-rbac-roles.md): Restrict who can create and edit JWT verification strategies in the first place.

- [Rotate provider credentials without downtime](/products/affinidi-trust-fabric/agent-stream/how-to-guides/security/rotate-provider-credentials-without-downtime.md): Apply the same credential-hygiene discipline to the provider side of a surface.

- [OPA policies](/products/affinidi-trust-fabric/agent-stream/concepts/opa-policies.md): Gate requests on the subject and claims this authentication step establishes.

## Related

- [Source authentication reference](/products/affinidi-trust-fabric/agent-stream/reference/security/source-authentication.md): Every JWT bearer, API key, and mTLS field, and the identity each produces.

- [Security and access control](/products/affinidi-trust-fabric/agent-stream/concepts/security-and-access-control.md): The conceptual model for all four authentication methods together.

- [OPA policies reference](/products/affinidi-trust-fabric/agent-stream/reference/policies/opa-policies.md): The source_auth.claims field a Rego policy can evaluate against.
