Apache APISIX JWT authentication with jwt-auth

How to validate JWTs from your own services at the Apache APISIX gateway with jwt-auth, including algorithm choices, token sources, key handling, and the breaking changes from 3.11 to 3.17.

On this page

When jwt-auth is the right way to validate your service tokens in APISIX

Use jwt-auth when your own services issue JWTs and you want APISIX to reject bad tokens before requests reach upstreams. The plugin checks the token signature and claims at the gateway, so upstreams receive only requests that already carry a token signed with a key you configured. It fits platform teams that control the token issuer, can share a signing secret or public key with the gateway, and want a simple per-consumer model without running a separate identity service for machine-to-machine calls. Per the APISIX jwt-auth documentation, the plugin supports HS256 (the default), HS384, HS512, RS256 through RS512, ES256 through ES512, PS256 through PS512 and EdDSA. It reads the token from the Authorization header first, then the jwt query parameter, then the jwt cookie, and it verifies exp and nbf by default. Confirm the exact algorithm list and option names against the jwt-auth plugin page for the APISIX version you deploy, because validation rules changed across recent releases.

Choose openid-connect instead when an identity provider issues the tokens, when you need token introspection or revocation checks, when users sign in through a browser, or when you want the gateway to follow the provider's key rotation through discovery. Choose key-auth when clients are simple partners or scripts that present a static API key and you do not need claims, expiry or signature validation. If your issuer is a single internal service and clients are trusted systems, jwt-auth is usually the smallest correct option. Before committing, confirm three things with your service team: which algorithm they sign with, whether they can publish a public key or must share a secret with the gateway, and which claims they always set. Those answers decide the consumer design and the key storage, and they determine whether the signing secret can live in a secrets store you already run.

Which jwt-auth settings matter and when each fits

This table compares the jwt-auth choices that have to agree between APISIX and the service that issues tokens: signing algorithm, key material, token source and time checks. Read each row by asking what your issuer already produces, then confirm the matching setting in APISIX before rollout.

SettingOption and fitWhat the issuing service must matchCheck before go-live
Signing algorithmHS256 is the default and suits a single trusted service that shares one secret with the gatewaySame algorithm in the token header and a shared secret in the consumer recordConfirm the algorithm name in each token header matches the configured value exactly
Asymmetric RSARS256 to RS512 suits issuers that keep a private key and let the gateway verify with a public keySigns with the private key and publishes or shares the matching public keyConfirm the public key in APISIX matches the issuer key pair, not a rotated or old key
Asymmetric ECDSAES256 to ES512 gives smaller signatures and suits teams that already run elliptic curve keysSigns with an EC private key on the matching curve for the chosen algorithmConfirm the curve matches the algorithm, since a mismatch fails verification
RSA-PSS and EdDSAPS256 to PS512 and EdDSA suit issuers whose libraries or policy require themUses PSS padding or an Ed25519 style key pair that the gateway is configured to acceptConfirm the issuer library emits the exact variant you select in APISIX
Token sourceAuthorization header is the normal choice for API clients, with query or cookie as fallbacksSends the token in the header your clients use, and avoids placing it in URLs that get loggedConfirm which sources your clients actually send and disable fallbacks you do not need
Key identityConsumer key identifies the issuer, so each token must carry the matching key claimIncludes the consumer key value in the token claims or header that APISIX readsConfirm one consumer per issuer or application to avoid ambiguous key matches
Expiry and not-beforeexp and nbf are verified by default, so tokens without valid times are rejectedSets exp for every token and sets nbf only where the issuer can keep clocks alignedConfirm test tokens with expired and future nbf values are denied
Clock skewA small tolerance absorbs drift between the issuer and gateway clocks, and a wide tolerance weakens expiryKeeps issuer and gateway clocks synchronized through NTP or equivalentConfirm the tolerance you choose and the time sync source on every gateway node
Required claimsConfigured claims ensure tokens carry the fields your routes depend on, as enforced from 3.17.0Includes every claim listed in the consumer or route configurationConfirm the claim names and values with the issuer team, since a missing claim now fails

How to configure jwt-auth on a route, step by step

This sequence takes a team from an empty APISIX instance to a route that accepts only JWTs signed by its own services, with a test result recorded for each token case. It is written for platform engineers who will run the gateway after the build.

  1. Confirm the APISIX version and plugin schema

    Before writing any configuration, confirm the APISIX release you run and open the jwt-auth plugin documentation for that version. Field names, defaults and required settings changed across the 3.11 to 3.17 range, so the documentation for your version is the reference for every later step. Check that the Admin API answers on the port your deployment mode uses (9180 in traditional mode) and that the gateway serves traffic on 9080. You are done when you can fetch the plugin schema for jwt-auth from your instance and it matches the documentation you are following.

  2. Create a consumer with a jwt-auth credential

    Create a consumer that represents the service or application whose tokens the gateway will accept. Attach a jwt-auth credential to it through the Admin API, setting the key, the algorithm and either a shared secret for HS256 or a public key for asymmetric algorithms. Use a consumer name and key that identify the issuing service, not a person, and store the secret in your secrets manager rather than in a shared file. You are done when the Admin API returns the consumer with its credential and the credential key appears in the list of consumer credentials.

  3. Choose the signing algorithm and key material

    Decide which algorithm your issuing service uses and match the gateway to it exactly. HS256 is the default and uses a shared secret, while RS256 to RS512, ES256 to ES512, PS256 to PS512 and EdDSA use a public key on the gateway side. Asymmetric verification keeps the signing key with the issuer, which is usually the better fit when the gateway is not the token issuer. Ask your identity owner which algorithm the issuer emits and whether the key ID must be present. You are done when the algorithm and key material on the gateway match what the issuer signs with, confirmed by decoding one token from the issuer.

  4. Attach jwt-auth to a route

    Create or update the route that serves the protected API and enable the jwt-auth plugin on it. Keep the route narrow, so that only the paths that need a token are protected and health checks or public endpoints stay on separate routes. If you use a token location other than the default authorization header, such as a query parameter or cookie, set that explicitly and record why, because it affects logging and caching of URLs. You are done when the route configuration saved in the gateway lists jwt-auth and the upstream is unchanged.

  5. Test a valid token and a missing token

    Send a request with a token that the issuer signed with the registered key and a valid expiry, and confirm the gateway forwards it to the upstream with a success response. Then send the same request with no token. The gateway should reject it with an authentication error rather than forwarding it. Record the status codes and any headers the upstream receives, since these become your baseline for regression checks after upgrades. You are done when the valid request succeeds, the missing-token request is refused, and both results are saved.

  6. Test expired, not-yet-valid and wrong-algorithm tokens

    Generate test tokens with the issuer or a test tool: one with an exp claim in the past, one with an nbf claim in the future, and one signed with an algorithm the consumer does not register, such as switching HS256 to a different algorithm while keeping the same key. Send each to the route. Expect rejection for all three, and confirm the rejection reason in the error log matches the case. Check the clock skew of the gateway and issuer hosts separately, since small drift can cause valid tokens to be refused near expiry. You are done when each invalid case is refused for the expected reason and the results are recorded next to the valid case.

  7. Record the configuration and the test evidence

    Export the consumer and route configuration, store it in version control, and keep the test results from the previous step with the version of APISIX they were run against. Note which field names you confirmed against the documentation and any value you set that differs from the default. Ask your security or compliance owner to review the evidence before the route serves production traffic. You are done when the configuration and test record can be reproduced from the repository and the reviewer has signed off in your change system.

What changed in jwt-auth between APISIX 3.11 and 3.17

Three changes in the jwt-auth plugin between APISIX 3.11.0 and 3.17.0 can affect routes that worked before an upgrade. The first is that 3.11.0 removed the jwt-auth signing endpoint and the need to upload private keys to APISIX. If your team previously issued tokens from the gateway, those tokens now have to come from your own identity or application services, and APISIX only verifies them. Check whether any consumer, script or runbook still calls a signing route or stores a private key in the gateway configuration, and move signing to the service that owns the key before the upgrade.

The second change is in 3.14.0, which requires a configured secret for every algorithm except RS256 and ES256. Consumers using HS256, the plugin default, or other secret-based algorithms without a secret value will fail configuration checks, so review each consumer object for the secret field and for the algorithm it names. For asymmetric algorithms, confirm that the consumer holds the correct public key material. Test a sample token against each route in a staging instance with the same APISIX version you plan to run in production.

The third change, in 3.17.0, enforces algorithm matching before signature verification and requires configured claims. A token whose header algorithm does not match the consumer configuration is now rejected before the signature is checked, which removes ambiguity but can break tokens from issuers that changed algorithms without notice. Required claims must also be present in every token. Ask your token issuers which algorithm and claims they send, and confirm the APISIX configuration against the jwt-auth plugin documentation and the APISIX changelog before scheduling the upgrade.

Security risks in JWT validation at the gateway

JWT validation at the gateway is only as strong as the settings around it: which algorithms are accepted, where the secret or key lives, how tokens travel, and how clocks are compared. Each card below covers one risk in the jwt-auth configuration and the check that closes it.

Algorithm confusion

A verifier that trusts the algorithm named in the token header can be tricked into accepting a forged token, for example by switching from RS256 to HS256 and signing with a public key. Since APISIX 3.17.0, jwt-auth enforces algorithm matching before signature verification. Confirm that each consumer or route pins the single algorithm your issuer uses, and test that a token signed with a different algorithm is rejected.

Weak HS256 secrets

HS256 tokens are only as safe as the shared secret. A short or guessable secret can be brute-forced offline from any captured token. Since APISIX 3.14.0, a secret is required for algorithms other than RS256 and ES256. Generate a long random value, store it in your secrets manager, and confirm that the consumer secret is not copied into Git, tickets or logs.

Public key rotation gaps

When an asymmetric issuer rotates signing keys, consumers that still hold the old public key will reject valid tokens, and consumers that keep retired keys may accept tokens that should no longer be trusted. Plan the overlap window, add the new public key before the issuer switches, and remove the old key on a set date. Confirm how your issuer publishes keys and who owns each consumer key record.

Tokens in query strings

jwt-auth reads tokens from the jwt query parameter as well as the header. Query strings are written to access logs, proxy logs, browser history and Referer headers, so a bearer token placed there can leak to anyone with log access. Restrict token input to the Authorization header where clients allow it, and set your log format to omit query arguments for these routes.

Cookie tokens and CSRF

When jwt-auth reads the jwt cookie, the browser attaches the token to cross-site requests unless the cookie is scoped and marked correctly. That opens the route to cross-site request forgery for state-changing calls. Set the cookie with HttpOnly, Secure and an appropriate SameSite value, and require a separate anti-CSRF control on write operations. Confirm this with your web team before enabling cookie input.

Clock skew and time checks

The exp and nbf claims are checked by default, so a gateway clock that drifts from the issuer can reject good tokens or accept expired ones. Tokens with short lifetimes make the problem more visible. Confirm that gateway hosts sync to a trusted time source, decide how much skew your issuers and gateways can tolerate, and test expiry and not-before behavior with tokens issued just before and after the boundary.

How to plan jwt-auth rollout without breaking live clients

Start with an inventory, because the effort of a jwt-auth rollout is set by how many token issuers and routes you have and by which signing algorithms those issuers use. List every APISIX route that enables jwt-auth, every consumer that carries a jwt-auth credential, and every service that issues tokens to those routes. For each issuer, record the algorithm in the token header, the claims it always sets (for example exp, nbf, iss or aud), and where clients place the token: the Authorization header, the jwt query parameter or the jwt cookie. Clients that send tokens in the query string or cookie are the ones most likely to break silently, so confirm their usage with the owning teams rather than assuming it from the configuration.

Next, test tokens from each issuer against the exact APISIX version you plan to run, not against the version you run today. Upgrades that remove the signing endpoint, require a secret for algorithms other than RS256 and ES256, enforce algorithm matching before signature verification, or require configured claims will reject tokens that were accepted before. Build a test matrix that covers each issuer, algorithm, route and token location, and include expired and not-yet-valid tokens so you can confirm that exp and nbf behave as your identity team expects. Stage the same configuration in a non-production environment with production-like routes, then run the matrix against it. Check the APISIX changelog for the release range you are crossing, and confirm with your vendor or platform team any issuer that uses a key format the plugin does not accept in the new version.

Keep a rollback path before you change anything in production. Export the current route and consumer configuration from the Admin API, keep the previous APISIX package or image available, and agree on a window in which the old gateway or old routes can take traffic again. Where possible, move one route group at a time and watch rejected requests by consumer and route. If a client fails only in one token location or with one algorithm, roll back that route and fix the issuer or consumer configuration before retrying. Document each decision so that the owners of each issuer know what changed, when, and what they must do before the next stage.

Limits to confirm in your environment before you rely on jwt-auth

The jwt-auth plugin checks signatures, expiry and claims, but the exact behavior depends on your APISIX version, your issuer's token contents and your key material. The cards below list the points to confirm with the vendor documentation and with tests against your own tokens before any route depends on them.

Clock skew handling for exp and nbf

The plugin verifies exp and nbf by default, but the tolerance for clock differences between your token issuer and the gateway nodes is a detail to confirm in the jwt-auth documentation for your version. Ask how skew is applied to each check. Then test a token issued just before its nbf time and one just after its exp time, with the gateway clock offset by your expected drift, so the behavior is known before production traffic arrives.

Issuer claims against required claims

APISIX 3.17.0 requires configured claims, so a token that lacks a claim your route expects can fail even when its signature is valid. Compare the claims your identity service actually writes (for example, the issuer, subject and expiry claims) with the claims listed in your route configuration. Confirm that claim names and value types match exactly, since a renamed or differently typed claim is a common cause of unexpected rejections.

Key and secret format per algorithm

The accepted key formats depend on the algorithm. HMAC algorithms use a shared secret, while RS, ES, PS and EdDSA algorithms use public keys in the format the plugin expects. Since 3.14.0, a secret is required for algorithms other than RS256 and ES256. Confirm the PEM or string format your issuer exports, check line endings and encoding, and test each algorithm your issuer uses rather than assuming one format works for all of them.

Algorithm matching before verification

Since 3.17.0, the plugin requires the token's algorithm to match the configured algorithm before signature verification. Confirm that your issuer signs with the exact algorithm set on the consumer or route, and that it does not switch algorithms during key rotation. A mismatch will fail the request even when the key itself is correct, so include a rotation test in your checks.

Behavior on your APISIX version

Plugin behavior changed across the 3.11 to 3.17 range, including removal of the signing endpoint and private key upload in 3.11.0. Confirm the exact APISIX version you will run, read the changelog entries between your current version and the target, and rerun your token tests after every upgrade. Keep the version pinned in your deployment so a routine image update does not change validation rules silently.

Questions teams ask before validating JWTs in APISIX

What drives the cost of a jwt-auth rollout in APISIX?

The cost follows the number of routes, token issuers and key types you need to validate, plus how much of the design work your team already has. Each issuer adds a set of claims, algorithms and key-handling decisions, and each route group adds a test matrix covering valid, expired, not-yet-valid and wrong-algorithm tokens. A written scope should list the issuers, the routes that need protection, the consumer model and the test cases before any quote is given. Recurring costs come from key rotation, plugin version upgrades and changes to issuers or claims, which are usually handled as a separate retainer.

How long does a scoped jwt-auth rollout take?

Duration depends mainly on the number of routes, the number of token issuers and whether the upstream services already emit the claims you need. A single issuer protecting a small set of routes is a much smaller job than several issuers across a full API estate with staged cutover. DeployOpen agrees timelines in the written scope, so ask for a timeline tied to named routes and issuers rather than a generic estimate. Ask your team to confirm the APISIX version in use first, because the jwt-auth behavior changed in 3.11, 3.14 and 3.17 and that affects test effort.

What does our team need to provide before the work starts?

Plan to provide the following inputs before design begins:

  • Sample tokens from each issuer, including expired and malformed examples, from a non-production environment
  • Issuer configuration details: the iss value, the signing algorithm and the claims your services expect
  • Access to public keys or shared secrets through your approved secret store, never by email or chat
  • Access to a staging gateway and the Admin API in your own infrastructure
  • A named owner who can approve route and consumer mapping decisions

Confirm with each issuer team which algorithm they sign with and whether they rotate keys.

Can our in-house team implement jwt-auth without a partner?

Yes, a team with gateway and identity experience can implement jwt-auth, and the APISIX documentation for the jwt-auth plugin is the primary reference. The harder parts are usually not the plugin configuration itself but the design choices: which algorithm to allow, how to model consumers, how to handle clock skew across services and how to test denials before rollout. Teams that have not run a gateway in production often underestimate the test matrix. A partner is most useful when the scope is wide, the issuers are many or the team has limited time to build test evidence. Either way, you keep the gateway in your own infrastructure.

Which jwt-auth settings cause the most production incidents?

The most common problems come from accepting the wrong algorithm, trusting a key that does not match the issuer, and mismatched clock settings between issuers and the gateway. Tokens that pass signature checks but lack required claims cause silent authorization gaps, so confirm which claims are mandatory in your version. Check that the exp and nbf checks behave as you expect, and test tokens that are just outside the allowed skew window. Keep allowed algorithms as narrow as your issuers permit, and record which key is used for each route in your change log.

Does moving to a newer APISIX version change jwt-auth behavior?

Yes. The APISIX changelog records changes to jwt-auth across 3.11, 3.14 and 3.17. Version 3.11.0 removed the signing endpoint and the need to upload private keys, 3.14.0 requires a secret for algorithms other than RS256 and ES256, and 3.17.0 enforces algorithm matching before signature verification and requires configured claims. Read the CHANGELOG for every version between your current release and your target before you plan the upgrade, and retest tokens from each issuer after the change. Confirm your current version with your own environment before estimating effort.

Does DeployOpen provide ongoing support after jwt-auth goes live?

Ongoing support is available as a retainer, and it can cover key rotation support, plugin version upgrades, reviews of new issuers and retesting after APISIX releases. Support is separate from the fixed-scope implementation, so agree its scope and response expectations in writing before go-live. Ask what is included in the retainer, how issuer and claim changes are requested and who on your side approves production changes. DeployOpen does not publish a price list, so the cost follows from the written scope.

Which APISIX release to target for jwt-auth work

Choose the APISIX release you will run before you write any jwt-auth configuration, and treat that choice as a design decision. The downloads page lists APISIX 3.19.0 as released on September 28, 2026, and it does not mark any release as long-term support. No version therefore carries a support label you can rely on, so the support commitment has to come from your own plan or your partner's written scope. Pin the exact version in your container image tags or package versions, and record the reason for that choice in the design document so later upgrades start from a known baseline.

The jwt-auth changes from 3.11 to 3.17 apply in sequence, so a gateway on an older release must review every change in that range, not only the last one. Version 3.11 removed the jwt-auth signing endpoint and the need to upload private keys, so any token issuance you relied on inside APISIX must move to your own identity service. Version 3.14 requires a secret for algorithms other than RS256 and ES256, so HS256 configurations need a secret before they load. Version 3.17 enforces algorithm matching before signature verification and requires configured claims, so existing routes that accepted loosely defined tokens may stop validating. Map each change against your current consumer and route configuration, and list the ones that affect you.

Confirm the target release against the project's CHANGELOG before you commit, because the changelog is the record of behavior changes, including patch releases that touch authentication. Then test that release in staging with a token set that covers every algorithm you accept, every claim you require, and a few deliberately invalid tokens, such as an expired token and one signed with the wrong algorithm. Ask whoever will support the gateway to confirm in writing which release and patch level they will operate, so the version in production is one that someone has agreed to maintain.

How DeployOpen scopes and delivers jwt-auth work

A jwt-auth engagement is defined in writing before any configuration changes. The scope fixes which routes, token issuers, algorithms and token sources are in play, and the test cases that prove them. The cards below follow that order from agreement through handover and ongoing support.

Written scope before build

The scope lists every route that requires a JWT, each issuer your services use, the algorithms each issuer signs with, and the token sources to accept. It also records the claims that must be present, such as exp and nbf, and the clock skew tolerance agreed with your platform team. Anything not listed is treated as out of scope until it is added in writing.

Algorithm and key decisions

Each issuer's signing algorithm is matched to a verification method: a shared secret for HS256 or a public key for RS256 or ES256. The scope records who owns each key, where it is stored, and how it is rotated. Private signing keys stay with your token issuer, since APISIX 3.11.0 removed the need to upload them.

Build in your infrastructure

Implementation runs in your cloud accounts, data centers or air-gapped network, against the APISIX deployment you already operate. Consumer objects, route bindings and any key material are created through your change process, so the configuration can be reviewed and reproduced. Nothing is installed in a DeployOpen-hosted environment.

Valid and invalid token tests

Verification covers both paths: tokens that should pass, and tokens that should be rejected for a wrong algorithm, an expired exp, a premature nbf, a missing configured claim, a bad signature, or a token presented in an unexpected location. Results are captured per route and per issuer, so a failing case points to a specific rule. The test cases come from the written scope and are rerun after any change.

Documentation and handover

Deliverables include the route and consumer inventory, the algorithm and key register, the token source settings, the test case list with results, and the steps to rotate a key or add an issuer. Your team receives these with the configuration so they can operate the setup without DeployOpen. Confirm the format and storage location of these documents in the scope.

Optional retainer for upgrades

Plugin behavior has changed across APISIX releases, so jwt-auth settings need review at each upgrade. A retainer can cover re-running the test cases against a new APISIX version, reviewing the changelog for affected settings, and planning the change window. Ask in the quote which upgrades and response times the retainer includes.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.