Skip to main content

jwt-auth

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-Indentifier, 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.

Examples

The examples below demonstrate how you can work with the jwt-auth plugin for different scenarios.

Use JWT for Consumer Authentication

The following example demonstrates how to implement JWT for consumer key authentication.

Create a consumer jack:

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_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_API_KEY}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"secret": "jack-hs256-secret"
}
}
}'

Create a route with jwt-auth plugin:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "jwt-route",
"uri": "/headers",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

To issue a JWT for jack, you could use JWT.io's debugger or other utilities. If you are using JWT.io's debugger, do the following:

  • Select HS256 in the Algorithm dropdown.
  • Update the secret in the Verify Signature section to be jack-hs256-secret.
  • Update payload with consumer key jack-key; and add exp or nbf in UNIX timestamp.
note

If you are using API7 Enterprise, the requirement of exp or nbf is not mandatory. You can optionally include these claims and use the claims_to_verify parameter to configure which claim to verify.

Your payload should look similar to the following:

{
"key": "jack-key",
"nbf": 1729132271
}

Copy the generated JWT under the Encoded section and save to a variable:

jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.0VDKUzNkSaa_H5g_rGNbNtDcKJ9fBGgcGC56AsVsV-I

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"
}
}

In 30 seconds, the token should expire. Send a request with the same token to verify:

curl -i "http://127.0.0.1:9080/headers" -H "Authorization: ${jwt_token}"

You should receive an HTTP/1.1 401 Unauthorized response similar to the following:

{"message":"failed to verify jwt"}

The following example demonstrates how to accept JWT in specified header, query string, and cookie.

Create a consumer jack:

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_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_API_KEY}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"secret": "jack-hs256-secret"
}
}
}'

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_API_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
}
}
}'

To issue a JWT for jack, you could use JWT.io's debugger or other utilities. If you are using JWT.io's debugger, do the following:

  • Select HS256 in the Algorithm dropdown.
  • Update the secret in the Verify Signature section to be jack-hs256-secret.
  • Update payload with consumer key jack-key; and add exp or nbf in UNIX timestamp.
note

If you are using API7 Enterprise, the requirement of exp or nbf is not mandatory. You can optionally include these claims and use the claims_to_verify parameter to configure which claim to verify.

Your payload should look similar to the following:

{
"key": "jack-key",
"nbf": 1729132271
}

Copy the generated JWT under the Encoded section and save to a variable:

jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.0VDKUzNkSaa_H5g_rGNbNtDcKJ9fBGgcGC56AsVsV-I

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": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY5NTEyOTA0NH0.EiktFX7di_tBbspbjmqDKoWAD9JG39Wo_CAQ1LZ9voQ",
...
},
...
}

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": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY5NTEyOTA0NH0.EiktFX7di_tBbspbjmqDKoWAD9JG39Wo_CAQ1LZ9voQ"
},
"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"
}

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=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY5NTEyOTA0NH0.EiktFX7di_tBbspbjmqDKoWAD9JG39Wo_CAQ1LZ9voQ",
...
},
...
}

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:

JACK_JWT_AUTH_KEY=jack-key

Create a consumer jack:

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_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_API_KEY}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "$env://JACK_JWT_AUTH_KEY",
"secret": "jack-hs256-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_API_KEY}" \
-d '{
"id": "jwt-route",
"uri": "/get",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

To issue a JWT for jack, you could use JWT.io's debugger or other utilities. If you are using JWT.io's debugger, do the following:

  • Select HS256 in the Algorithm dropdown.
  • Update the secret in the Verify Signature section to be jack-hs256-secret.
  • Update payload with consumer key jack-key; and add exp or nbf in UNIX timestamp.
note

If you are using API7 Enterprise, the requirement of exp or nbf is not mandatory. You can optionally include these claims and use the claims_to_verify parameter to configure which claim to verify.

Your payload should look similar to the following:

{
"key": "jack-key",
"nbf": 1729132271
}

Copy the generated JWT under the Encoded section and save to a variable:

jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.0VDKUzNkSaa_H5g_rGNbNtDcKJ9fBGgcGC56AsVsV-I

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 similar to the following:

{
"args": {},
"headers": {
"Accept": "*/*",
"Authorization": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2OTUxMzMxNTUsImtleSI6Imp3dC1rZXkifQ.jiKuaAJqHNSSQCjXRomwnQXmdkC5Wp5VDPRsJlh1WAQ",
...
},
...
}

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/

Create a secret and configure the Vault address and other connection information:

curl "http://127.0.0.1:9180/apisix/admin/secrets/vault/jwt" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"uri": "https://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_API_KEY}" \
-d '{
"username": "jack"
}'

Create jwt-auth credential for the consumer and reference the secret in key:

curl "http://127.0.0.1:9180/apisix/admin/consumers/jack/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "$secret://vault/jwt/jack/jwt-key",
"secret": "vault-hs256-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_API_KEY}" \
-d '{
"id": "jwt-route",
"uri": "/get",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

Set jwt-auth key value to be jwt-vault-key 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-key=jwt-vault-key"

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 debugger or other utilities. If you are using JWT.io's debugger, do the following:

  • Select HS256 in the Algorithm dropdown.
  • Update the secret in the Verify Signature section to be vault-hs256-secret.
  • Update payload with consumer key jwt-vault-key; and add exp or nbf in UNIX timestamp.
note

If you are using API7 Enterprise, the requirement of exp or nbf is not mandatory. You can optionally include these claims and use the claims_to_verify parameter to configure which claim to verify.

Your payload should look similar to the following:

{
"key": "jwt-vault-key",
"nbf": 1729132271
}

Copy the generated JWT under the Encoded section and save to a variable:

jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqd3QtdmF1bHQta2V5IiwibmJmIjoxNzI5MTMyMjcxfQ.faiN93LNP1lGSXqAb4empNJKMRWop8-KgnU58VQn1EE

Sending request with the token as header:

curl -i "http://127.0.0.1:9080/get" -H "Authorization: ${jwt_token}"

You should receive an HTTP/1.1 200 OK response similar to the following:

{
"args": {},
"headers": {
"Accept": "*/*",
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqd3QtdmF1bHQta2V5IiwiZXhwIjoxNjk1MTM4NjM1fQ.Au2liSZ8eQXUJR3SJESwNlIfqZdNyRyxIJK03L4dk_g",
...
},
...
}

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 debugger and do the following:

  • Select RS256 in the Algorithm dropdown.
  • Copy and paste the key content into the Verify Signature section.
  • Update the payload with key matching the consumer key you would like to use; and exp or nbf in UNIX timestamp.
note

If you are using API7 Enterprise, the requirement of exp or nbf is not mandatory. You can optionally include these claims and use the claims_to_verify parameter to configure which claim to verify.

The configuration should look similar to the following:


complete configuration of JWT generation on jwt.io

Copy the JWT on the left and save to an environment variable:

jwt_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsImV4cCI6MTczNDIzMDQwMH0.XjqM0oszmCggwZs-8PUIlJv8wPJON1la2ET5v70E6TCE32Yq5ibrl-1azaK7IreAer3HtnVHeEfII2rR02v8xfR1TPIjU_oHov4qC-A4tLTbgqGVXI7fCy2WFm3PFh6MEKuRe6M3dCQtCAdkRRQrBr1gWFQZhV3TNeMmmtyIfuJpB7cp4DW5pYFsCcoE1Nw6Tz7dt8k0tPBTPI2Mv9AYfMJ30LHDscOaPNtz8YIk_TOkV9b9mhQudUJ7J_suCZMRxD3iL655jTp2gKsstGKdZa0_W9Reu4-HY3LSc5DS1XtfjuftpuUqgg9FvPU0mK_b0wT_Rq3lbYhcHb9GZ72qiQ

Create a consumer jack:

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "jack"
}'

Create jwt-auth credential for the consumer and reference the secret in key:

curl "http://127.0.0.1:9180/apisix/admin/consumers/jack/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"algorithm": "RS256",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnE0h4k/GWfEbYO/yE2MPjHtNKDLNz4mv1KNIPLxY2ccjPYOtjuug+iZ4MujLV59YfrHriTs0H8jweQfff3pRSMjyEK+4qWTY3TeKBXIEa3pVDeoedSJrgjLBVio6xH7et8ir+QScScfLaJHGB4/l3DDGyEhO782a9teY8brn5hsWX5uLmDJvxtTGAHYi847XOcx2UneW4tZ8wQ6JGBSiSg5qAHan4dFZ7CpixCNNqEcSK6EQ7lKOLeFGG8ys/dHBIEasU4oMlCuJH77+XQQ/shchy+vm9oZfP+grLZkV+nKAd8MQZsid7ZJ/fiB/BmnhGrjtIfh98jwxSx4DgdLhdwIDAQAB\n-----END PUBLIC KEY-----",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCcTSHiT8ZZ8Rtg7/ITYw+Me00oMs3Pia/Uo0g8vFjZxyM9g62O66D6Jngy6MtXn1h+seuJOzQfyPB5B99/elFIyPIQr7ipZNjdN4oFcgRrelUN6h51ImuCMsFWKjrEft63yKv5BJxJx8tokcYHj+XcMMbISE7vzZr215jxuufmGxZfm4uYMm/G1MYAdiLzjtc5zHZSd5bi1nzBDokYFKJKDmoAdqfh0VnsKmLEI02oRxIroRDuUo4t4UYbzKz90cEgRqxTigyUK4kfvv5dBD+yFyHL6+b2hl8/6CstmRX6coB3wxBmyJ3tkn9+IH8GaeEauO0h+H3yPDFLHgOB0uF3AgMBAAECggEARpY68Daw0Funzq5uN70r/3iLztSqx8hZpQEclXlF8wwQ6S33iqz1JSOMcwlZE7g9wfHd+jrHfndDypT4pVx7KxC86TZCghWuLrFvXqgwQM2dbcxGdwXVYZZEZAJsSeM19+/jYnFnl5ZoUVBMC4w79aX9j+O/6mKDUmjphHmxUuRCFjN0w7BRoYwmS796rSf1eoOcSXh2G9Ycc34DUFDfGpOzabndbmMfOz7W0DyUBG23fgLhNChTUGq8vMaqKXkQ8JKeKdEugSmRGz42HxjWoNlIGBDyB8tPNPT6SXsu/JBskdf9Gb71OWiub381oXC259sz+1K1REb1KSkgyC+bkQKBgQDKCnwXaf8aOIoJPCG53EqQfKScCIYQrvp1Uk3bs5tfYN4HcI3yAUnOqQ3Ux3eY9PfS37urlJXCfCbCnZ6P6xALZnN+aL2zWvZArlHvD6vnXiyevwK5IY+o2EW02h3A548wrGznQSsfX0tum22bEVlRuFfBbpZpizXwrV4ODSNhTwKBgQDGC27QQxah3yq6EbOhJJlJegjawVXEaEp/j4fD3qe/unLbUIFvCz6j9BAbgocDKzqXxlpTtIbnsesdLo7KM3MtYL0XO/87HIsBj9XCVgMkFCcM6YZ6fHnkJl0bs3haU4N9uI/wpokvfvXJp7iC9LUCseBdBj+N6T230HWiSbPjWQKBgQC8zzGKO/8vRNkSqkQmSczQ2/qE6p5G5w6eJy0lfOJdLswvDatJFpUf8PJA/6svoPYb9gOO5AtUNeuPAfeVLSnQTYzu+/kTrJTme0GMdAvE60gtjfmAgvGa64mw6gjWJk+1P92B+2/OIKMAmXXDbWIYMXqpBKzBs1vUMF/uJ68BlwKBgQDEivQem3YKj3/HyWmLstatpP7EmrqTgSzuC3OhX4b7L/5sySirG22/KKgTpSZ4bp5noeJiz/ZSWrAK9fmfkg/sKOV/+XsDHwCVPDnX86SKWbWnitp7FK2jTq94nlQC0H7edhvjqGLdUBJ9XoYu8MvzMLSJnXnVTHSDx832kU6FgQKBgQCbw4Eiu2IcOduIAokmsZl8Smh9ZeyhP2B/UBa1hsiPKQ6bw86QJr2OMbRXLBxtx+HYIfwDo4vXEE862PfoQyu6SjJBNmHiid7XcV06Z104UQNjP7IDLMMF+SASMqYoQWg/5chPfxBgIXnfWqw6TMmND3THY4Oj4Nhf4xeUg3HsaA==\n-----END PRIVATE KEY-----"
}
}
}'

❶ Configure the consumer key to be jack-key.

❷ Configure the JWT signing algorithm to be RS256.

❸ Configure the RSA public key.

❹ Configure the RSA private key.

tip

You should add a newline character after the opening line and before the closing line, for example -----BEGIN PRIVATE KEY-----\n......\n-----END PRIVATE KEY-----.

The key content can be directly concatenated.

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_API_KEY}" \
-d '{
"id": "jwt-route",
"uri": "/headers",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

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 similar to the following:

{
"headers": {
"Accept": "*/*",
"Authorization": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsImV4cCI6MTczNDIzMDQwMH0.XjqM0oszmCggwZs-8PUIlJv8wPJON1la2ET5v70E6TCE32Yq5ibrl-1azaK7IreAer3HtnVHeEfII2rR02v8xfR1TPIjU_oHov4qC-A4tLTbgqGVXI7fCy2WFm3PFh6MEKuRe6M3dCQtCAdkRRQrBr1gWFQZhV3TNeMmmtyIfuJpB7cp4DW5pYFsCcoE1Nw6Tz7dt8k0tPBTPI2Mv9AYfMJ30LHDscOaPNtz8YIk_TOkV9b9mhQudUJ7J_suCZMRxD3iL655jTp2gKsstGKdZa0_W9Reu4-HY3LSc5DS1XtfjuftpuUqgg9FvPU0mK_b0wT_Rq3lbYhcHb9GZ72qiQ",
...
}
}

Add Consumer Custom ID to Header

The following example demonstrates how you can attach a consumer custom ID to authenticated request in the Consumer-Custom-Id header, which can be used to implement additional logics as needed.

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_API_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_API_KEY}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"secret": "jack-hs256-secret"
}
}
}'

Create a route with jwt-auth:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "jwt-auth-route",
"uri": "/anything",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

To issue a JWT for jack, you could use JWT.io's debugger or other utilities. If you are using JWT.io's debugger, do the following:

  • Select HS256 in the Algorithm dropdown.
  • Update the secret in the Verify Signature section to be jack-hs256-secret.
  • Update payload with consumer key jack-key; and add exp or nbf in UNIX timestamp.
note

If you are using API7 Enterprise, the requirement of exp or nbf is not mandatory. You can optionally include these claims and use the claims_to_verify parameter to configure which claim to verify.

Your payload should look similar to the following:

{
"key": "jack-key",
"nbf": 1729132271
}

Copy the generated JWT under the Encoded section and save to a variable:

jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.0VDKUzNkSaa_H5g_rGNbNtDcKJ9fBGgcGC56AsVsV-I

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": "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-Consumer-Custom-Id": "495aec6a",
"X-Forwarded-Host": "127.0.0.1"
}
}

If you would like to attach more consumer custom headers to authenticated requests, see Enterprise attach-consumer-label plugin.

Rate Limit with Anonymous Consumer

The anonymous consumer is an Enterprise feature.

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.

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_API_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_API_KEY}" \
-d '{
"id": "cred-jack-jwt-auth",
"plugins": {
"jwt-auth": {
"key": "jack-key",
"secret": "jack-hs256-secret"
}
}
}'

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_API_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_API_KEY}" \
-d '{
"id": "jwt-auth-route",
"uri": "/anything",
"plugins": {
"jwt-auth": {
"anonymous_consumer": "anonymous"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

To issue a JWT for jack, you could use JWT.io's debugger or other utilities. If you are using JWT.io's debugger, do the following:

  • Select HS256 in the Algorithm dropdown.
  • Update the secret in the Verify Signature section to be jack-hs256-secret.
  • Update payload with role user, permission read, and consumer key jack-key; as well as exp or nbf in UNIX timestamp.
note

If you are using API7 Enterprise, the requirement of exp or nbf is not mandatory. You can optionally include these claims and use the claims_to_verify parameter to configure which claim to verify.

Your payload should look similar to the following:

{
"key": "jack-key",
"nbf": 1729132271
}

Copy the generated JWT under the Encoded section and save to a variable:

jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJqYWNrLWtleSIsIm5iZiI6MTcyOTEzMjI3MX0.hjtSsEILpko14zb8-ibyxrB2tA5biYY9JrFm3do69vs

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

API7.ai Logo

API Management for Modern Architectures with Edge, API Gateway, Kubernetes, and Service Mesh.

Product

API7 Cloud

SOC2 Type IIISO 27001HIPAAGDPRRed Herring

Copyright © APISEVEN PTE. LTD 2019 – 2024. Apache, Apache APISIX, APISIX, and associated open source project names are trademarks of the

Apache Software Foundation