jwt-auth.md
June 3, 2026 ยท View on GitHub
import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
Description
The jwt-auth Plugin supports the use of JSON Web Token (JWT) as a mechanism for clients to authenticate themselves before accessing Upstream resources.
Once enabled, the Plugin exposes an endpoint to create JWT credentials by Consumers. The process generates a token that client requests should carry to identify themselves to APISIX. The token can be included in the request URL query string, request header, or cookie. APISIX will then verify the token to determine if a request should be allowed or denied to access Upstream resources.
When a Consumer is successfully authenticated, APISIX adds additional headers, such as X-Consumer-Username, X-Credential-Identifier, and other Consumer custom headers if configured, to the request, before proxying it to the Upstream service. The Upstream service will be able to differentiate between consumers and implement additional logics as needed. If any of these values is not available, the corresponding header will not be added.
Attributes
The following attributes are available for configurations on Consumers or Credentials.
| Name | Type | Required | Default | Valid values | Description |
|---|---|---|---|---|---|
| key | string | True | non-empty | A unique key that identifies the credential for a Consumer. | |
| secret | string | False | non-empty | Shared key used to sign and verify the JWT when the algorithm is symmetric. Required when using HS256, HS384, or HS512 as the algorithm. This field supports saving the value in Secret Manager using the APISIX Secret resource. | |
| public_key | string | False | Public key in PEM format required by the configured asymmetric algorithm. Required if the algorithm is RS256, ES256, RS384, RS512, ES384, ES512, PS256, PS384, PS512, or EdDSA. This field supports saving the value in Secret Manager using the APISIX Secret resource. | ||
| algorithm | string | False | HS256 | HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512, EdDSA | Encryption algorithm. |
| exp | integer | False | 86400 | >=1 | Expiry time of the token in seconds. If you are not using APISIX to sign the JWT, this parameter is ignored and you should specify the expiration in the payload when signing the JWT. |
| base64_secret | boolean | False | false | Set to true if the secret is base64 encoded. | |
| lifetime_grace_period | integer | False | 0 | >=0 | Grace period in seconds. Used to account for clock skew between the server generating the JWT and the server validating the JWT. |
NOTE: encrypt_fields = {"secret"} is also defined in the schema, which means that the field will be stored encrypted in etcd. See encrypted storage fields.
The following attributes are available for configurations on Routes or Services.
| Name | Type | Required | Default | Valid values | Description |
|---|---|---|---|---|---|
| header | string | False | authorization | The header to get the token from. | |
| query | string | False | jwt | The query string to get the token from. Lower priority than header. | |
| cookie | string | False | jwt | The cookie to get the token from. Lower priority than query. | |
| hide_credentials | boolean | False | false | If true, do not pass the header, query, or cookie with JWT to Upstream services. | |
| anonymous_consumer | string | False | Anonymous Consumer name. If configured, allow anonymous users to bypass the authentication. | ||
| claims_to_verify | array[string] | False | ["exp", "nbf"] | combination of exp and nbf | Specify the JWT claim(s) to verify, to ensure that the token is used within its allowed timeframe. Note that this is not the claims required to be presented in the payload, but the claims to verify, if presented. |
| store_in_ctx | boolean | False | false | If true, store JWT payload in the request context variable ctx.jwt_auth_payload. This allows plugins executed after jwt-auth on the same request to retrieve and use the payload information. | |
| realm | string | False | jwt | The realm to include in the WWW-Authenticate header when authentication fails. | |
| key_claim_name | string | False | key | The claim in the JWT payload that identifies the associated secret, such as iss. |
You can implement jwt-auth with HashiCorp Vault to store and fetch secrets and RSA key pairs from its encrypted KV engine using the APISIX Secret resource.
Examples
The examples below demonstrate how you can work with the jwt-auth Plugin for different scenarios.
:::note
You can fetch the admin_key from conf/config.yaml and save to an environment variable with the following command:
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
:::
Use JWT for Consumer Authentication
The following example demonstrates how to implement JWT for Consumer key authentication.
<Tabs groupId="api" defaultValue="dashboard" values={[ {label: 'Admin API', value: 'dashboard'}, {label: 'ADC', value: 'adc'}, {label: 'Ingress Controller', value: 'ingress'} ]}>
Create a Consumer jack:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"username": "jack"
}'
Create jwt-auth Credential for the Consumer:
curl "http://127.0.0.1:9180/apisix/admin/consumers/jack/credentials" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"secret": "jack-hs256-secret-that-is-very-long"
}
}
}'
Create a Route with jwt-auth Plugin:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "jwt-route",
"uri": "/headers",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
Create a Consumer with jwt-auth Credential and a Route with jwt-auth Plugin configured as such:
consumers:
- username: jack
credentials:
- name: jwt-auth
type: jwt-auth
config:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
services:
- name: jwt-auth-service
routes:
- name: jwt-route
uris:
- /headers
plugins:
jwt-auth: {}
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
<Tabs groupId="k8s-api" defaultValue="gateway-api" values={[ {label: 'Gateway API', value: 'gateway-api'}, {label: 'APISIX Ingress Controller', value: 'apisix-ingress-controller'} ]}>
Create a Consumer with jwt-auth Credential and a Route with jwt-auth Plugin configured as such:
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: jack
spec:
gatewayRef:
name: apisix
credentials:
- type: jwt-auth
name: primary-cred
config:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: jwt-auth-plugin-config
spec:
plugins:
- name: jwt-auth
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: jwt-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /headers
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: jwt-auth-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f jwt-auth-ic.yaml
Create a consumer with jwt-auth credential and a route with jwt-auth plugin enabled as such:
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: jack
spec:
ingressClassName: apisix
authParameter:
jwtAuth:
value:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: jwt-route
spec:
ingressClassName: apisix
http:
- name: jwt-route
match:
paths:
- /headers
upstreams:
- name: httpbin-external-domain
plugins:
- name: jwt-auth
enable: true
config:
_meta:
disable: false
Apply the configuration to your cluster:
kubectl apply -f jwt-auth-ic.yaml
To issue a JWT for jack, you could use JWT.io's JWT encoder or other utilities. If you are using JWT.io's JWT encoder, do the following:
- Fill in
HS256as the algorithm. - Update the secret in the Valid secret section to be
jack-hs256-secret-that-is-very-long. - Update payload with Consumer key
jack-key; and addexpornbfin UNIX timestamp.
Your payload should look similar to the following:
{
"key": "jack-key",
"nbf": 1729132271
}
Copy the generated JWT and save to a variable:
export jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.UEPXy5jpid624T1XpfjM0PLY73LZPjV3Qt8yZ92kVuU
Send a request to the Route with the JWT in the Authorization header:
curl -i "http://127.0.0.1:9080/headers" -H "Authorization: ${jwt_token}"
You should receive an HTTP/1.1 200 OK response similar to the following:
{
"headers": {
"Accept": "*/*",
"Authorization": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjY2NDk2NDAsImtleSI6ImphY2sta2V5In0.kdhumNWrZFxjUvYzWLt4lFr546PNsr9TXuf0Az5opoM",
"Host": "127.0.0.1",
"User-Agent": "curl/8.6.0",
"X-Amzn-Trace-Id": "Root=1-66ea951a-4d740d724bd2a44f174d4daf",
"X-Consumer-Username": "jack",
"X-Credential-Identifier": "cred-jack-jwt-auth",
"X-Forwarded-Host": "127.0.0.1"
}
}
Send a request with an invalid token:
curl -i "http://127.0.0.1:9080/headers" -H "Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjY2NDk2NDAsImtleSI6ImphY2sta2V5In0.kdhumNWrZFxjU_random_random"
You should receive an HTTP/1.1 401 Unauthorized response similar to the following:
{"message":"failed to verify jwt"}
Carry JWT in Request Header, Query String, or Cookie
The following example demonstrates how to accept JWT in specified header, query string, and cookie.
<Tabs groupId="api" defaultValue="dashboard" values={[ {label: 'Admin API', value: 'dashboard'}, {label: 'ADC', value: 'adc'}, {label: 'Ingress Controller', value: 'ingress'} ]}>
Create a Consumer jack:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"username": "jack"
}'
Create jwt-auth Credential for the Consumer:
curl "http://127.0.0.1:9180/apisix/admin/consumers/jack/credentials" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"secret": "jack-hs256-secret-that-is-very-long"
}
}
}'
Create a Route with jwt-auth Plugin, and specify the request parameters carrying the token:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "jwt-route",
"uri": "/get",
"plugins": {
"jwt-auth": {
"header": "jwt-auth-header",
"query": "jwt-query",
"cookie": "jwt-cookie"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
Create a Consumer with jwt-auth Credential and a Route with jwt-auth Plugin configured as such:
consumers:
- username: jack
credentials:
- name: jwt-auth
type: jwt-auth
config:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
services:
- name: jwt-auth-service
routes:
- name: jwt-route
uris:
- /get
plugins:
jwt-auth:
header: jwt-auth-header
query: jwt-query
cookie: jwt-cookie
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
<Tabs groupId="k8s-api" defaultValue="gateway-api" values={[ {label: 'Gateway API', value: 'gateway-api'}, {label: 'APISIX Ingress Controller', value: 'apisix-ingress-controller'} ]}>
Create a Consumer with jwt-auth Credential and a Route with jwt-auth Plugin configured as such:
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: jack
spec:
gatewayRef:
name: apisix
credentials:
- type: jwt-auth
name: primary-cred
config:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: jwt-auth-plugin-config
spec:
plugins:
- name: jwt-auth
config:
_meta:
disable: false
header: jwt-auth-header
query: jwt-query
cookie: jwt-cookie
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: jwt-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: jwt-auth-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f jwt-auth-ic.yaml
Create a consumer with jwt-auth credential and a route with jwt-auth plugin configured as such:
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: jack
spec:
ingressClassName: apisix
authParameter:
jwtAuth:
value:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: jwt-route
spec:
ingressClassName: apisix
http:
- name: jwt-route
match:
paths:
- /get
upstreams:
- name: httpbin-external-domain
plugins:
- name: jwt-auth
enable: true
config:
_meta:
disable: false
header: jwt-auth-header
query: jwt-query
cookie: jwt-cookie
Apply the configuration to your cluster:
kubectl apply -f jwt-auth-ic.yaml
To issue a JWT for jack, you could use JWT.io's JWT encoder or other utilities. If you are using JWT.io's JWT encoder, do the following:
- Fill in
HS256as the algorithm. - Update the secret in the Valid secret section to be
jack-hs256-secret-that-is-very-long. - Update payload with Consumer key
jack-key; and addexpornbfin UNIX timestamp.
Your payload should look similar to the following:
{
"key": "jack-key",
"nbf": 1729132271
}
Copy the generated JWT and save to a variable:
export jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.UEPXy5jpid624T1XpfjM0PLY73LZPjV3Qt8yZ92kVuU
Verify With JWT in Header
Sending request with JWT in the header:
curl -i "http://127.0.0.1:9080/get" -H "jwt-auth-header: ${jwt_token}"
You should receive an HTTP/1.1 200 OK response similar to the following:
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"Jwt-Auth-Header": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.UEPXy5jpid624T1XpfjM0PLY73LZPjV3Qt8yZ92kVuU",
...
},
...
}
Verify With JWT in Query String
Sending request with JWT in the query string:
curl -i "http://127.0.0.1:9080/get?jwt-query=${jwt_token}"
You should receive an HTTP/1.1 200 OK response similar to the following:
{
"args": {
"jwt-query": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.UEPXy5jpid624T1XpfjM0PLY73LZPjV3Qt8yZ92kVuU"
},
"headers": {
"Accept": "*/*",
...
},
"origin": "127.0.0.1, 183.17.233.107",
"url": "http://127.0.0.1/get?jwt-query=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY5NTEyOTA0NH0.EiktFX7di_tBbspbjmqDKoWAD9JG39Wo_CAQ1LZ9voQ"
}
Verify With JWT in Cookie
Sending request with JWT in the cookie:
curl -i "http://127.0.0.1:9080/get" --cookie jwt-cookie=${jwt_token}
You should receive an HTTP/1.1 200 OK response similar to the following:
{
"args": {},
"headers": {
"Accept": "*/*",
"Cookie": "jwt-cookie=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.UEPXy5jpid624T1XpfjM0PLY73LZPjV3Qt8yZ92kVuU",
...
},
...
}
Manage Secrets in Environment Variables
The following example demonstrates how to save jwt-auth Consumer key to an environment variable and reference it in configuration.
APISIX supports referencing system and user environment variables configured through the NGINX env directive.
Save the key to an environment variable. If you are running APISIX in Docker, you should set the environment variable using the -e flag when starting the container.
export JACK_JWT_SECRET=jack-hs256-secret-that-is-very-long
<Tabs groupId="api" defaultValue="dashboard" values={[ {label: 'Admin API', value: 'dashboard'}, {label: 'ADC', value: 'adc'} ]}>
Create a Consumer jack:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"username": "jack"
}'
Create jwt-auth Credential for the Consumer and reference the environment variable:
curl "http://127.0.0.1:9180/apisix/admin/consumers/jack/credentials" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"secret": "$env://JACK_JWT_SECRET"
}
}
}'
Create a Route with jwt-auth enabled:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "jwt-route",
"uri": "/get",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
Create a Consumer with jwt-auth Credential referencing an environment variable and a Route with jwt-auth Plugin enabled as such:
consumers:
- username: jack
credentials:
- name: jwt-auth
type: jwt-auth
config:
key: jack-key
secret: $env://JACK_JWT_SECRET
services:
- name: jwt-auth-service
routes:
- name: jwt-route
uris:
- /get
plugins:
jwt-auth: {}
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
To issue a JWT for jack, you could use JWT.io's JWT encoder or other utilities. If you are using JWT.io's JWT encoder, do the following:
- Fill in
HS256as the algorithm. - Update the secret in the Valid secret section to be
jack-hs256-secret-that-is-very-long. - Update payload with Consumer key
jack-key; and addexpornbfin UNIX timestamp.
Your payload should look similar to the following:
{
"key": "jack-key",
"nbf": 1729132271
}
Copy the generated JWT and save to a variable:
export jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.UEPXy5jpid624T1XpfjM0PLY73LZPjV3Qt8yZ92kVuU
Sending request with JWT in the header:
curl -i "http://127.0.0.1:9080/get" -H "Authorization: ${jwt_token}"
You should receive an HTTP/1.1 200 OK response.
Manage Secrets in Secret Manager
The following example demonstrates how to manage jwt-auth Consumer key in HashiCorp Vault and reference it in Plugin configuration.
Start a Vault development server in Docker:
docker run -d \
--name vault \
-p 8200:8200 \
--cap-add IPC_LOCK \
-e VAULT_DEV_ROOT_TOKEN_ID=root \
-e VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200 \
vault:1.9.0 \
vault server -dev
APISIX currently supports Vault KV engine version 1. Enable it in Vault:
docker exec -i vault sh -c "VAULT_TOKEN='root' VAULT_ADDR='http://0.0.0.0:8200' vault secrets enable -path=kv -version=1 kv"
You should see a response similar to the following:
Success! Enabled the kv secrets engine at: kv/
<Tabs groupId="api" defaultValue="dashboard" values={[ {label: 'Admin API', value: 'dashboard'}, {label: 'ADC', value: 'adc'} ]}>
Create a Secret and configure the Vault address and other connection information. Adjust the Vault address accordingly:
curl "http://127.0.0.1:9180/apisix/admin/secrets/vault/jwt" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"uri": "http://127.0.0.1:8200",
"prefix": "kv/apisix",
"token": "root"
}'
Create a Consumer jack:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"username": "jack"
}'
Create jwt-auth Credential for the Consumer and reference the Secret:
curl "http://127.0.0.1:9180/apisix/admin/consumers/jack/credentials" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jwt-vault-key",
"secret": "$secret://vault/jwt/jack/jwt-secret"
}
}
}'
Create a Route with jwt-auth enabled:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "jwt-route",
"uri": "/get",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
Create a Secret and configure the Vault address. Adjust the Vault address accordingly:
secrets:
- name: vault-jwt
vault:
url: http://127.0.0.1:8200
prefix: kv/apisix
token: root
consumers:
- username: jack
credentials:
- name: jwt-auth
type: jwt-auth
config:
key: jwt-vault-key
secret: $secret://vault-jwt/jack/jwt-secret
services:
- name: jwt-auth-service
routes:
- name: jwt-route
uris:
- /get
plugins:
jwt-auth: {}
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
Set jwt-auth key value to be vault-hs256-secret-that-is-very-long in Vault:
docker exec -i vault sh -c "VAULT_TOKEN='root' VAULT_ADDR='http://0.0.0.0:8200' vault kv put kv/apisix/jack jwt-secret=vault-hs256-secret-that-is-very-long"
You should see a response similar to the following:
Success! Data written to: kv/apisix/jack
To issue a JWT, you could use JWT.io's JWT encoder or other utilities. If you are using JWT.io's JWT encoder, do the following:
- Fill in
HS256as the algorithm. - Update the secret in the Valid secret section to be
vault-hs256-secret-that-is-very-long. - Update payload with Consumer key
jwt-vault-key; and addexpornbfin UNIX timestamp.
Your payload should look similar to the following:
{
"key": "jwt-vault-key",
"nbf": 1729132271
}
Copy the generated JWT and save to a variable:
export jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqd3QtdmF1bHQta2V5IiwibmJmIjoxNzI5MTMyMjcxfQ.i2pLj7QcQvnlSjB7iV5V522tIV43boQRtee7L0rwlkQ
Send a request with the token in the header:
curl -i "http://127.0.0.1:9080/get" -H "Authorization: ${jwt_token}"
You should receive an HTTP/1.1 200 OK response.
Sign JWT with RS256 Algorithm
The following example demonstrates how you can use asymmetric algorithms, such as RS256, to sign and validate JWT when implementing JWT for Consumer authentication. You will be generating RSA key pairs using openssl and generating JWT using JWT.io to better understand the composition of JWT.
Generate a 2048-bit RSA private key and extract the corresponding public key in PEM format:
openssl genrsa -out jwt-rsa256-private.pem 2048
openssl rsa -in jwt-rsa256-private.pem -pubout -out jwt-rsa256-public.pem
You should see jwt-rsa256-private.pem and jwt-rsa256-public.pem generated in your current working directory.
Visit JWT.io's JWT encoder and do the following:
- Fill in
RS256as the algorithm. - Copy and paste the private key content into the SIGN JWT: PRIVATE KEY section.
- Update payload with Consumer key
jack-key; and addexpornbfin UNIX timestamp.
Your payload should look similar to the following:
{
"key": "jack-key",
"nbf": 1729132271
}
Copy the generated JWT and save to a variable:
export jwt_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.K-I13em84kAcyH1jfIJl7ls_4jlwg1GzEzo5_xrDu-3wt3Xa3irS6naUsWpxX-a-hmcZZxRa9zqunqQjUP4kvn5e3xg2f_KyCR-_ZbwqYEPk3bXeFV1l4iypv6z5L7W1Niharun-dpMU03b1Tz64vhFx6UwxNL5UIZ7bunDAo_BXZ7Xe8rFhNHvIHyBFsDEXIBgx8lNYMq8QJk3iKxZhZZ5Om7lgYjOOKRgew4WkhBAY0v1AkO77nTlvSK0OEeeiwhkROyntggyx-S-U222ykMQ6mBLxkP4Cq5qHwXD8AUcLk5mhEij-3QhboYnt7yhKeZ3wDSpcjDvvL2aasC25ng
<Tabs groupId="api" defaultValue="dashboard" values={[ {label: 'Admin API', value: 'dashboard'}, {label: 'ADC', value: 'adc'}, {label: 'Ingress Controller', value: 'ingress'} ]}>
Create a Consumer jack:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"username": "jack"
}'
Create jwt-auth Credential for the Consumer and configure the RSA keys. You should add a newline character after the opening line and before the closing line of the public key, for example -----BEGIN PUBLIC KEY-----\n......\n-----END PUBLIC KEY-----. The key content can be directly concatenated.
curl "http://127.0.0.1:9180/apisix/admin/consumers/jack/credentials" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"algorithm": "RS256",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoTxe7ZPycrEP0SK4OBA2\n0OUQsDN9gSFSHVvx/t++nZNrFxzZnV6q6/TRsihNXUIgwaOu5icFlIcxPL9Mf9UJ\na5/XCQExp1TxpuSmjkhIFAJ/x5zXrC8SGTztP3SjkhYnQO9PKVXI6ljwgakVCfpl\numuTYqI+ev7e45NdK8gJoJxPp8bPMdf8/nHfLXZuqhO/btrDg1x+j7frDNrEw+6B\nCK2SsuypmYN+LwHfaH4Of7MQFk3LNIxyBz0mdbsKJBzp360rbWnQeauWtDymZxLT\nATRNBVyl3nCNsURRTkc7eyknLaDt2N5xTIoUGHTUFYSdE68QWmukYMVGcEHEEPkp\naQIDAQAB\n-----END PUBLIC KEY-----"
}
}
}'
Create a Route with the jwt-auth Plugin:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "jwt-route",
"uri": "/headers",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
Create a Consumer with jwt-auth Credential using RS256 algorithm and a Route with jwt-auth Plugin enabled as such:
consumers:
- username: jack
credentials:
- name: jwt-auth
type: jwt-auth
config:
key: jack-key
algorithm: RS256
public_key: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoTxe7ZPycrEP0SK4OBA2
0OUQsDN9gSFSHVvx/t++nZNrFxzZnV6q6/TRsihNXUIgwaOu5icFlIcxPL9Mf9UJ
a5/XCQExp1TxpuSmjkhIFAJ/x5zXrC8SGTztP3SjkhYnQO9PKVXI6ljwgakVCfpl
umuTYqI+ev7e45NdK8gJoJxPp8bPMdf8/nHfLXZuqhO/btrDg1x+j7frDNrEw+6B
CK2SsuypmYN+LwHfaH4Of7MQFk3LNIxyBz0mdbsKJBzp360rbWnQeauWtDymZxLT
ATRNBVyl3nCNsURRTkc7eyknLaDt2N5xTIoUGHTUFYSdE68QWmukYMVGcEHEEPkp
aQIDAQAB
-----END PUBLIC KEY-----
services:
- name: jwt-auth-service
routes:
- name: jwt-route
uris:
- /headers
plugins:
jwt-auth: {}
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
<Tabs groupId="k8s-api" defaultValue="gateway-api" values={[ {label: 'Gateway API', value: 'gateway-api'}, {label: 'APISIX Ingress Controller', value: 'apisix-ingress-controller'} ]}>
Create a Consumer with jwt-auth Credential using RS256 algorithm and a Route with jwt-auth Plugin enabled as such:
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: jack
spec:
gatewayRef:
name: apisix
credentials:
- type: jwt-auth
name: primary-cred
config:
key: jack-key
algorithm: RS256
public_key: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoTxe7ZPycrEP0SK4OBA2
0OUQsDN9gSFSHVvx/t++nZNrFxzZnV6q6/TRsihNXUIgwaOu5icFlIcxPL9Mf9UJ
a5/XCQExp1TxpuSmjkhIFAJ/x5zXrC8SGTztP3SjkhYnQO9PKVXI6ljwgakVCfpl
umuTYqI+ev7e45NdK8gJoJxPp8bPMdf8/nHfLXZuqhO/btrDg1x+j7frDNrEw+6B
CK2SsuypmYN+LwHfaH4Of7MQFk3LNIxyBz0mdbsKJBzp360rbWnQeauWtDymZxLT
ATRNBVyl3nCNsURRTkc7eyknLaDt2N5xTIoUGHTUFYSdE68QWmukYMVGcEHEEPkp
aQIDAQAB
-----END PUBLIC KEY-----
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: jwt-auth-plugin-config
spec:
plugins:
- name: jwt-auth
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: jwt-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /headers
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: jwt-auth-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f jwt-auth-ic.yaml
Create a consumer with jwt-auth credential using RS256 algorithm and a route with jwt-auth plugin enabled as such:
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: jack
spec:
ingressClassName: apisix
authParameter:
jwtAuth:
value:
key: jack-key
algorithm: RS256
public_key: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoTxe7ZPycrEP0SK4OBA2
0OUQsDN9gSFSHVvx/t++nZNrFxzZnV6q6/TRsihNXUIgwaOu5icFlIcxPL9Mf9UJ
a5/XCQExp1TxpuSmjkhIFAJ/x5zXrC8SGTztP3SjkhYnQO9PKVXI6ljwgakVCfpl
umuTYqI+ev7e45NdK8gJoJxPp8bPMdf8/nHfLXZuqhO/btrDg1x+j7frDNrEw+6B
CK2SsuypmYN+LwHfaH4Of7MQFk3LNIxyBz0mdbsKJBzp360rbWnQeauWtDymZxLT
ATRNBVyl3nCNsURRTkc7eyknLaDt2N5xTIoUGHTUFYSdE68QWmukYMVGcEHEEPkp
aQIDAQAB
-----END PUBLIC KEY-----
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: jwt-route
spec:
ingressClassName: apisix
http:
- name: jwt-route
match:
paths:
- /headers
upstreams:
- name: httpbin-external-domain
plugins:
- name: jwt-auth
enable: true
config:
_meta:
disable: false
Apply the configuration to your cluster:
kubectl apply -f jwt-auth-ic.yaml
To verify, send a request to the Route with the JWT in the Authorization header:
curl -i "http://127.0.0.1:9080/headers" -H "Authorization: ${jwt_token}"
You should receive an HTTP/1.1 200 OK response.
Add Consumer Custom ID to Header
The following example demonstrates how you can attach a Consumer custom ID to authenticated request in the X-Consumer-Custom-ID header, which can be used to implement additional logics as needed.
<Tabs groupId="api" defaultValue="dashboard" values={[ {label: 'Admin API', value: 'dashboard'}, {label: 'ADC', value: 'adc'}, {label: 'Ingress Controller', value: 'ingress'} ]}>
Create a Consumer jack with a custom ID label:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"username": "jack",
"labels": {
"custom_id": "495aec6a"
}
}'
Create jwt-auth Credential for the Consumer:
curl "http://127.0.0.1:9180/apisix/admin/consumers/jack/credentials" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"secret": "jack-hs256-secret-that-is-very-long"
}
}
}'
Create a Route with jwt-auth:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "jwt-auth-route",
"uri": "/anything",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
Create a Consumer with jwt-auth Credential and a Route with jwt-auth Plugin enabled as such:
consumers:
- username: jack
labels:
custom_id: "495aec6a"
credentials:
- name: jwt-auth
type: jwt-auth
config:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
services:
- name: jwt-auth-service
routes:
- name: jwt-auth-route
uris:
- /anything
plugins:
jwt-auth: {}
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
Create a consumer with jwt-auth credential and a route with jwt-auth plugin enabled:
<Tabs groupId="k8s-api" defaultValue="gateway-api" values={[ {label: 'Gateway API', value: 'gateway-api'}, {label: 'APISIX CRD', value: 'apisix-crd'} ]}>
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: jack
labels:
custom_id: "495aec6a"
spec:
gatewayRef:
name: apisix
credentials:
- type: jwt-auth
name: primary-cred
config:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: jwt-auth-plugin-config
spec:
plugins:
- name: jwt-auth
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: jwt-auth-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: jwt-auth-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f jwt-auth-ic.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: jack
labels:
custom_id: "495aec6a"
spec:
ingressClassName: apisix
authParameter:
jwtAuth:
value:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: jwt-auth-route
spec:
ingressClassName: apisix
http:
- name: jwt-auth-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: jwt-auth
enable: true
config:
_meta:
disable: false
Apply the configuration to your cluster:
kubectl apply -f jwt-auth-ic.yaml
To issue a JWT for jack, you could use JWT.io's JWT encoder or other utilities. If you are using JWT.io's JWT encoder, do the following:
- Fill in
HS256as the algorithm. - Update the secret in the Valid secret section to be
jack-hs256-secret-that-is-very-long. - Update payload with Consumer key
jack-key; and addexpornbfin UNIX timestamp.
Your payload should look similar to the following:
{
"key": "jack-key",
"nbf": 1729132271
}
Copy the generated JWT and save to a variable:
export jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.UEPXy5jpid624T1XpfjM0PLY73LZPjV3Qt8yZ92kVuU
To verify, send a request to the Route with the JWT in the Authorization header:
curl -i "http://127.0.0.1:9080/headers" -H "Authorization: ${jwt_token}"
You should see an HTTP/1.1 200 OK response similar to the following:
{
"headers": {
"Accept": "*/*",
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.UEPXy5jpid624T1XpfjM0PLY73LZPjV3Qt8yZ92kVuU",
"Host": "127.0.0.1",
"User-Agent": "curl/8.6.0",
"X-Amzn-Trace-Id": "Root=1-6873b19d-329331db76e5e7194c942b47",
"X-Consumer-Custom-Id": "495aec6a",
"X-Consumer-Username": "aic_jack",
"X-Credential-Identifier": "cred-jack-jwt-auth",
"X-Forwarded-Host": "127.0.0.1"
}
}
Rate Limit with Anonymous Consumer
The following example demonstrates how you can configure different rate limiting policies by regular and anonymous consumers, where the anonymous Consumer does not need to authenticate and has less quotas.
<Tabs groupId="api" defaultValue="dashboard" values={[ {label: 'Admin API', value: 'dashboard'}, {label: 'ADC', value: 'adc'}, {label: 'Ingress Controller', value: 'ingress'} ]}>
Create a regular Consumer jack and configure the limit-count Plugin to allow for a quota of 3 within a 30-second window:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"username": "jack",
"plugins": {
"limit-count": {
"count": 3,
"time_window": 30,
"rejected_code": 429
}
}
}'
Create the jwt-auth Credential for the Consumer jack:
curl "http://127.0.0.1:9180/apisix/admin/consumers/jack/credentials" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"secret": "jack-hs256-secret-that-is-very-long"
}
}
}'
Create an anonymous user anonymous and configure the limit-count Plugin to allow for a quota of 1 within a 30-second window:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"username": "anonymous",
"plugins": {
"limit-count": {
"count": 1,
"time_window": 30,
"rejected_code": 429
}
}
}'
Create a Route and configure the jwt-auth Plugin to accept anonymous Consumer anonymous from bypassing the authentication:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "jwt-auth-route",
"uri": "/anything",
"plugins": {
"jwt-auth": {
"anonymous_consumer": "anonymous"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
Configure Consumers with different rate limits and a Route that accepts anonymous users:
consumers:
- username: jack
plugins:
limit-count:
count: 3
time_window: 30
rejected_code: 429
policy: local
credentials:
- name: jwt-auth
type: jwt-auth
config:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
- username: anonymous
plugins:
limit-count:
count: 1
time_window: 30
rejected_code: 429
policy: local
services:
- name: anonymous-rate-limit-service
routes:
- name: jwt-auth-route
uris:
- /anything
plugins:
jwt-auth:
anonymous_consumer: anonymous
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
<Tabs groupId="k8s-api" defaultValue="gateway-api" values={[ {label: 'Gateway API', value: 'gateway-api'}, {label: 'APISIX Ingress Controller', value: 'apisix-ingress-controller'} ]}>
Configure Consumers with different rate limits and a Route that accepts anonymous users:
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: jack
spec:
gatewayRef:
name: apisix
credentials:
- type: jwt-auth
name: primary-key
config:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
plugins:
- name: limit-count
config:
count: 3
time_window: 30
rejected_code: 429
policy: local
---
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: anonymous
spec:
gatewayRef:
name: apisix
plugins:
- name: limit-count
config:
count: 1
time_window: 30
rejected_code: 429
policy: local
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: jwt-auth-plugin-config
spec:
plugins:
- name: jwt-auth
config:
anonymous_consumer: aic_anonymous # namespace_consumername
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: jwt-auth-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: jwt-auth-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f jwt-auth-ic.yaml
Configure consumers with different rate limits and a route that accepts anonymous users:
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: jack
spec:
ingressClassName: apisix
authParameter:
jwtAuth:
value:
key: jack-key
secret: jack-hs256-secret-that-is-very-long
plugins:
- name: limit-count
enable: true
config:
count: 3
time_window: 30
rejected_code: 429
policy: local
---
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: anonymous
spec:
ingressClassName: apisix
plugins:
- name: limit-count
enable: true
config:
count: 1
time_window: 30
rejected_code: 429
policy: local
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: jwt-auth-route
spec:
ingressClassName: apisix
http:
- name: jwt-auth-route
match:
paths:
- /headers
upstreams:
- name: httpbin-external-domain
plugins:
- name: jwt-auth
enable: true
config:
anonymous_consumer: aic_anonymous
Apply the configuration to your cluster:
kubectl apply -f jwt-auth-ic.yaml
To issue a JWT for jack, you could use JWT.io's JWT encoder or other utilities. If you are using JWT.io's JWT encoder, do the following:
- Fill in
HS256as the algorithm. - Update the secret in the Valid secret section to be
jack-hs256-secret-that-is-very-long. - Update payload with Consumer key
jack-key; and addexpornbfin UNIX timestamp.
Your payload should look similar to the following:
{
"key": "jack-key",
"nbf": 1729132271
}
Copy the generated JWT and save to a variable:
export jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.UEPXy5jpid624T1XpfjM0PLY73LZPjV3Qt8yZ92kVuU
To verify the rate limiting, send five consecutive requests with jack's JWT:
resp=$(seq 5 | xargs -I{} curl "http://127.0.0.1:9080/anything" -H "Authorization: ${jwt_token}" -o /dev/null -s -w "%{http_code}\n") && \
count_200=$(echo "$resp" | grep "200" | wc -l) && \
count_429=$(echo "$resp" | grep "429" | wc -l) && \
echo "200": $count_200, "429": $count_429
You should see the following response, showing that out of the 5 requests, 3 requests were successful (status code 200) while the others were rejected (status code 429).
200: 3, 429: 2
Send five anonymous requests:
resp=$(seq 5 | xargs -I{} curl "http://127.0.0.1:9080/anything" -o /dev/null -s -w "%{http_code}\n") && \
count_200=$(echo "$resp" | grep "200" | wc -l) && \
count_429=$(echo "$resp" | grep "429" | wc -l) && \
echo "200": $count_200, "429": $count_429
You should see the following response, showing that only one request was successful:
200: 1, 429: 4