Skip to main content
Version: Dev

JWT Authentication

AISIX can authenticate agents with short-lived credentials in JSON Web Token (JWT) format instead of long-lived caller API keys. A trust provider verifies each token against signing keys published in a JSON Web Key Set (JWKS) or against a shared secret. Each verified external identity maps to a caller API key and inherits its model access, rate limits, and usage attribution. In AISIX Cloud, the mapped key also carries its budget.

JWKS-based providers include Keycloak, Entra ID, Okta, Auth0, and other OIDC-compliant identity providers. AISIX can also verify HMAC-signed tokens from an issuer that shares a secret with the gateway. In both cases, AISIX verifies the token's signature and claims on every request. The agent does not need the caller API key's plaintext value.

Dashboard single sign-on for human operators and gateway JWT authentication for agent requests are independent. Configuring one does not affect the other.

How It Works

When an environment has at least one enabled trust provider, AISIX inspects each request's bearer token:

  1. If the bearer is a JWT, its iss (issuer) claim selects the trust provider: when iss equals an enabled provider's issuer, that provider alone verifies the token. A token whose issuer matches no enabled provider reaches only the enabled shared-secret providers that pin no issuer, and is rejected when none of them verifies it.
  2. AISIX verifies the token's signature against the provider's JSON Web Key Set (JWKS), or against its shared secret when the provider has one, and validates the registered claims: exp (expiration, always required), aud (audience, when the provider configures accepted audiences), and nbf (not-before) when present.
  3. The provider's required_scopes and bound_claims requirements are enforced.
  4. The value of the provider's identity claim (sub by default) selects the caller API key whose jwt_subject equals it and whose jwt_provider names this provider. The request then runs as that key. Scoping the binding to the provider means a second trusted provider cannot mint a token that impersonates this provider's identity.
  5. When no key binds the identity directly, the provider's claim mappings — priority-ordered rules matching the verified claims — can resolve the request to an existing key, so whole groups of identities share one governed key without per-identity registration. A token matching neither a binding nor a mapping is rejected.

AISIX rejects tokens that fail verification or do not map to a caller API key before the request reaches a provider, MCP server, or vector store. For a JWKS provider, signing-key rotation at the identity provider is picked up automatically, with no gateway restart.

Prerequisites

Before starting, prepare the following:

  • One of these configuration paths:
    • AISIX Cloud with an environment and an admin token that has the write scope. For On-Premises, follow the AISIX Cloud Quickstart. To request Hybrid Cloud access, contact API7.
    • An open-source AISIX gateway that loads a declarative resources.yaml file.
  • A system that issues JWT tokens to your agents, with the verification material for the method it uses:
    • For JWKS verification, prepare the expected issuer and either its JWKS endpoint URL or its OIDC discovery document (<issuer>/.well-known/openid-configuration).
    • For HMAC signing, prepare the shared secret. It must contain at least 32 UTF-8 bytes. The expected issuer and audiences are optional.
  • A model alias the caller should be allowed to use and, for the AISIX Cloud workflow, its model ID. If you have not created one yet, configure Provider Keys and Model Aliases first.
  • curl and jq. The open-source AISIX gateway also requires OpenSSL for the credential-generation command shown below.

A provider verified against a JWKS must sign tokens with an asymmetric algorithm supported by AISIX: RSA (RS256, RS384, RS512, PS256, PS384, or PS512), ECDSA (ES256 or ES384), or EdDSA. It rejects HMAC-signed tokens. To trust an issuer that signs with a shared secret, give the provider an hmac_secret instead, as described in Shared-Secret (HMAC) Providers.

Configure JWT Authentication

Configure the trust provider and identity-bound caller API key using the management path for your deployment.

Choose Trust Provider Settings

The same trust settings apply in AISIX Cloud and the open-source AISIX gateway, except for how issuer uniqueness is enforced:

FieldDescription
issuerExpected iss claim, compared exactly against the token. A configured issuer must be unique within an AISIX Cloud environment. In a resources file, enabled providers that set an issuer must use distinct values. It is required for JWKS verification and optional with hmac_secret; an issuer-less shared-secret provider does not check iss.
audiencesAccepted aud values. JWKS verification requires at least one, and the token must contain a match. With hmac_secret, omit the field or use an empty list to skip audience validation.
jwks_uriEndpoint the signing keys are fetched from. Omit it to resolve the endpoint from the issuer's OIDC discovery document. It must not be set together with hmac_secret.
hmac_secretShared secret that switches the provider to HMAC verification. Omit it for a provider verified against a JWKS. See Shared-Secret (HMAC) Providers.
identity_claimClaim whose value selects the caller API key, matched against each key's jwt_subject. Dots traverse nested objects, for example resource_access.account. Defaults to sub.
required_scopesScopes that must all be present in the token's scope claim (a space-delimited string or an array).
bound_claimsAdditional claim requirements. Each key names a claim, with dots traversing nested objects. A string claim must equal one of the expected values; an array claim must contain one of them.
leeway_secsClock-skew allowance from 0 to 300 seconds for the time-based claims. Defaults to 0.
enabledWhether the provider participates in authentication. Defaults to true.

For a JWKS provider, omitting jwks_uri makes AISIX resolve and cache the signing-key endpoint from the issuer's discovery document. Provide jwks_uri explicitly when the discovery document is not reachable from the gateway.

AISIX Cloud

Export the base URL, the admin token, the environment ID, and the model ID:

# AISIX_CP is the Admin API base URL; include /api and omit a trailing slash.
# The local On-Premises quickstart uses http://localhost:8080/api.
export AISIX_CP="YOUR_AISIX_CLOUD_ADMIN_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
export MODEL_ID="YOUR_MODEL_ID"

Register a Trust Provider

This example uses JWKS verification. Provide the issuer and at least one accepted audience:

curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/oidc_providers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "corp-keycloak",
"issuer": "https://sso.example.com/realms/agents",
"audiences": ["aisix-gateway"],
"required_scopes": ["ai.access"],
"bound_claims": {
"department": "ai-lab"
}
}' | jq

The response returns the created provider, including the defaults AISIX filled in:

{
"oidc_provider": {
"id": "b2c3d4e5-6789-4abc-def0-123456789abc",
"env_id": "9be9891a-6a53-4bd8-a897-a03fe38a1ca5",
"name": "corp-keycloak",
"issuer": "https://sso.example.com/realms/agents",
"audiences": ["aisix-gateway"],
"identity_claim": "sub",
"required_scopes": ["ai.access"],
"bound_claims": {
"department": "ai-lab"
},
"leeway_secs": 0,
"enabled": true,
"created_at": "2026-07-27T12:00:00Z",
"updated_at": "2026-07-27T12:00:00Z"
}
}

Bind a Caller API Key to an Identity

Create (or update) a caller API key with two fields set together:

  • jwt_subject: the external identity a verified token maps to. Set it to the value your token issuer puts in the claim named by the provider's identity_claim.
  • jwt_provider: the name of the trust provider allowed to assert that subject. Only a token issued by this provider is ever mapped to the key.
curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/api_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "billing-agent",
"allowed_models": ["'"$MODEL_ID"'"],
"jwt_subject": "agent-billing-01",
"jwt_provider": "corp-keycloak"
}' | jq

The jwt_provider and jwt_subject pair is unique within the environment, and both must be set together. Give each agent identity its own caller API key so model access, rate limits, and usage attribution apply independently. In AISIX Cloud, each identity also inherits the key's budget. Agents authenticate with their JWT, so you do not need to distribute the key's plaintext value.

Open-Source AISIX Gateway

For the open-source AISIX gateway, declare the OIDC provider and JWT-bound caller API key in resources.yaml. The model alias in allowed_models must also be defined in the file:

resources.yaml
_format_version: "1"

provider_keys:
- display_name: openai-prod
provider: openai
adapter: openai
api_key: ${OPENAI_API_KEY}
api_base: https://api.openai.com/v1

models:
- display_name: gpt-4o-prod
provider: openai
model_name: gpt-4o
provider_key: openai-prod

oidc_providers:
- name: corp-keycloak
issuer: https://sso.example.com/realms/agents
audiences: ["aisix-gateway"]
required_scopes: ["ai.access"]
bound_claims:
department: ai-lab

api_keys:
- display_name: billing-agent
key_env: BILLING_AGENT_KEY
allowed_models: ["gpt-4o-prod"]
jwt_subject: agent-billing-01
jwt_provider: corp-keycloak

api_key supplies the model provider credential from OPENAI_API_KEY.

key_env names the environment variable containing the caller API key's plaintext value.

AISIX requires the caller credential when loading any caller API key, even when the agent authenticates only with JWT tokens. Set both variables for the gateway process, and do not distribute BILLING_AGENT_KEY to the agent:

export OPENAI_API_KEY="YOUR_PROVIDER_API_KEY"
export BILLING_AGENT_KEY="$(openssl rand -hex 32)"

Validate and load the file as described in the Resources File Reference. After it loads, use the same JWT request shown in the next section.

Shared-Secret (HMAC) Providers

Some issuers sign tokens with a secret both sides hold rather than with a key pair published in a JWKS. Give the trust provider an hmac_secret to verify those tokens. The field is optional, and setting it changes how that one provider works:

  • Tokens are accepted only under HS256, HS384, or HS512.
  • Nothing is fetched: there is no JWKS request and no OIDC discovery. jwks_uri must not be set.
  • issuer and audiences become optional. When issuer is set, iss must match it. A nonempty audiences list requires aud to contain a listed value. Omitting either field skips that check; an empty audience list also skips audience validation.

Everything else behaves as it does for a JWKS provider. The exp claim remains mandatory. Identity claims, scope and claim requirements, claim mappings, clock-skew allowance, and caller-key bindings work the same way.

A provider without hmac_secret is unchanged: it fetches signing keys, accepts only the asymmetric algorithms listed under Prerequisites, and rejects HMAC-signed tokens.

Prefer asymmetric signing where you can

With a shared secret, the gateway holds a key that can also mint tokens. Leaking it allows an attacker to impersonate any identity the issuer can assert. Use a JWKS provider whenever the issuer can offer one. For the open-source gateway, keep the secret out of the file by referencing an environment variable.

Secret Handling

The secret's UTF-8 bytes are the HMAC key as-is. Nothing is base64-decoded or derived, so the issuer must sign with exactly the same byte string. The secret must be at least 32 bytes long.

A provider holds one secret. Rotate by updating the secret on the provider; tokens signed with the previous secret stop verifying as soon as the change reaches the gateway.

Provider Selection

When a token's iss equals an enabled provider's issuer, that provider alone verifies the token. A mismatch of mode or algorithm there is a 401, with no fallback to another provider.

Otherwise AISIX tries every enabled shared-secret provider that pins no issuer, in order of provider name, and the first one that verifies the token wins. There is no limit on how many are tried. If none verifies it, the token is rejected. A JWKS provider is never reached this way, because issuer is mandatory in that mode.

Give each issuer-less shared-secret provider a distinct secret. Providers that share one can verify the same tokens. The provider that sorts first by name wins, so the other provider's audience, scope, and claim requirements never apply.

Configure a Shared-Secret Provider

In AISIX Cloud, send hmac_secret when creating the provider. This example pins no issuer and no audiences, so the token's iss and aud claims are not checked:

curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/oidc_providers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "partner-hmac",
"hmac_secret": "YOUR_SHARED_SECRET_OF_AT_LEAST_32_BYTES",
"required_scopes": ["ai.access"]
}' | jq

The secret is write-only. It is never returned by a read, which reports "hmac_secret_set": true instead:

{
"oidc_provider": {
"id": "c3d4e5f6-7890-4abc-def0-123456789abc",
"name": "partner-hmac",
"audiences": [],
"identity_claim": "sub",
"required_scopes": ["ai.access"],
"hmac_secret_set": true,
"leeway_secs": 0,
"enabled": true
}
}

On an update, omit hmac_secret to keep the stored secret, send a new value to replace it, or send null to clear it. Clearing it switches the provider back to JWKS mode, which then requires issuer and at least one audience.

In the dashboard, the provider form offers a Verification method choice of JWKS / OIDC discovery or Shared secret (HMAC). The Shared secret field is entered as a password and is never shown again; when editing a provider that already has one, leave the field blank to keep it. The provider list shows each provider's mode.

For the open-source gateway, add the secret to the oidc_providers entry in resources.yaml through an environment variable, so the plaintext stays out of the file:

resources.yaml (OIDC provider)
oidc_providers:
- name: partner-hmac
hmac_secret: ${JWT_HMAC_SECRET}
required_scopes: ["ai.access"]
export JWT_HMAC_SECRET="YOUR_SHARED_SECRET_OF_AT_LEAST_32_BYTES"

Configuration Errors

AISIX rejects a provider that is configured inconsistently:

  • jwks_uri set together with hmac_secret.
  • A provider without hmac_secret that lacks an issuer or at least one audience.
  • An hmac_secret shorter than 32 bytes.

The AISIX Cloud Admin API answers 400 for each of these. In a resources file, the offending entry is rejected at load, reported by Configuration Status and counted in aisix_config_rejected_resources.

Gateway Version Requirement

Shared-secret providers require an AISIX gateway of version 1.5.0 or later. While an earlier gateway is registered in the target environment, AISIX Cloud refuses to save one with 422 and the error code DP_INCOMPATIBLE. Upgrade the gateways in that environment first.

Authenticate a Request

Have the agent obtain a token from the issuing system. Set the model alias and token, then send the token on the proxy API exactly like a caller API key:

# AISIX_PROXY is the gateway origin; omit a trailing slash and endpoint path.
# The local quickstarts use http://127.0.0.1:3000.
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
export MODEL_ALIAS="YOUR_MODEL_ALIAS"
export AGENT_JWT="eyJhbGciOiJSUzI1NiIsImtpZCI6..."

curl -sS -X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer $AGENT_JWT" \
-H "Content-Type: application/json" \
-d '{
"model": "'"$MODEL_ALIAS"'",
"messages": [{"role": "user", "content": "Hello"}]
}' | jq

AISIX verifies the token and maps it to the billing-agent key: its sub claim agent-billing-01 matches the key's jwt_subject, and the token's issuer resolves to the corp-keycloak provider named in the key's jwt_provider. The request then runs under that key's permissions. The token's aud must include aisix-gateway. It must also carry the ai.access scope and the department: ai-lab claim required by the provider.

Rejection Reasons

On OpenAI-style proxy routes, a rejected token carries a stable error.code so clients can react without parsing messages. Anthropic-style routes omit code and use the HTTP status and Anthropic-compatible error.type; see Headers and Error Codes.

OpenAI-style error.codeHTTP statusMeaning
jwt_expired401The token's exp deadline has passed. Fetch a fresh token.
jwt_invalid401The token is malformed or fails issuer, signature, signing algorithm, audience, required-claim, or not-before validation.
jwt_claims_rejected403The token is valid but does not satisfy the provider's required_scopes or bound_claims.
jwt_identity_unmapped401The configured identity claim is missing or is not a string, or the identity resolves to no key — no caller API key has matching jwt_provider and jwt_subject values and no claim mapping matched. Check the token claim, key binding, and mappings.
jwks_unavailable503AISIX could not resolve or fetch the provider's signing keys. Check the OIDC discovery or JWKS endpoint, then retry.

Key Rotation

This section covers providers verified against a JWKS. A shared-secret provider fetches nothing, so it is rotated by updating its hmac_secret.

When your identity provider introduces a signing key, an unrecognized key ID triggers a JWKS refresh. No configuration change or gateway restart is needed.

AISIX coalesces simultaneous outbound fetches for the same OIDC discovery document or JWKS URL. Requests wait for the shared fetch when the cache is empty, the configured JWKS URL has changed, or a token uses a newly rotated key. Requests that can use a stale cached result continue while the refresh runs.

After a fetch completes, successfully or unsuccessfully, AISIX waits at least one second before fetching the same discovery document or JWKS URL again. A request that needs new trust material during this interval may need to be retried.

AISIX treats cached discovery results and key sets as fresh for 10 minutes. After that interval, the next authentication request triggers a refresh. Once the refreshed set no longer contains a retired key, tokens signed by that key stop authenticating. If the discovery or JWKS endpoint is unavailable during a refresh, AISIX keeps the last successful result. Existing authentication can continue with the cached keys, but a retired key remains trusted until a later refresh succeeds.

Update or Remove a Trust Provider

AISIX Cloud

Use the Admin API to update an existing provider. For example, disable it to stop trusting its tokens while keeping its configuration:

export OIDC_PROVIDER_ID="b2c3d4e5-6789-4abc-def0-123456789abc"

curl -sS -X PATCH "$AISIX_CP/environments/$ENV_ID/oidc_providers/$OIDC_PROVIDER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": false}' | jq

Set enabled to true to trust the provider again. You can also update its issuer, accepted audiences, JWKS endpoint, shared secret, identity claim, required scopes, bound claims, or clock-skew allowance with the same PATCH operation. The provider name cannot be changed after creation.

Delete the provider to remove the trust entirely:

curl -sS -X DELETE "$AISIX_CP/environments/$ENV_ID/oidc_providers/$OIDC_PROVIDER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" | jq

Deleting a provider does not affect the caller API keys or their jwt_subject bindings. Those keys still authenticate with their plaintext values, and can be re-associated with a new provider later.

Open-Source AISIX Gateway

Edit the provider under oidc_providers in resources.yaml. Set enabled: false to disable it while retaining its configuration, change its fields to update the trust policy, or remove the entry to delete the provider.

The caller API key remains in api_keys when you disable or remove its provider. Its plaintext value continues to authenticate. To remove the JWT identity mapping as well, delete both jwt_subject and jwt_provider from the key.

After each change, validate and reload the file. Follow Reload a Resources File for the complete workflow.

Next Steps

  • JWT Claim Mappings: admit whole classes of identities — departments, groups, applications — through priority-ordered claim rules instead of per-identity bindings.
  • Keycloak Integration: a verified end-to-end walkthrough from a Keycloak realm to mapped, attributed requests.
  • Caller API Keys: manage the model access and other controls inherited by each mapped identity.
  • API Key and Model Rate Limits: limit the request volume or token usage of JWT-authenticated callers.
  • Configuration Propagation: understand how configuration changes reach AISIX gateways.