jwt-auth
is an authentication plugin that need to work with consumer
. Add JWT Authentication to a service
or route
.
The consumer
then adds its key to the query string parameter, request header, or cookie
to verify its request.
For more information on JWT, refer to JWT for more information.
jwt-auth
plugin can be integrated with HashiCorp Vault for storing and fetching secrets, RSA key pairs from its encrypted kv engine. See the examples below to have an overview of how things work.
Name | Type | Requirement | Default | Valid | Description |
---|---|---|---|---|---|
key | string | required | different consumer have different value, it's unique. different consumer use the same key , and there will be a request matching exception. | ||
secret | string | optional | encryption key. if you do not specify, the value is auto-generated in the background. | ||
public_key | string | optional | RSA public key, required when algorithm attribute selects RS256 algorithm. | ||
private_key | string | optional | RSA private key, required when algorithm attribute selects RS256 algorithm. | ||
algorithm | string | optional | “HS256” | [“HS256”, “HS512”, “RS256”] | encryption algorithm. |
exp | integer | optional | 86400 | [1,...] | token's expire time, in seconds |
base64_secret | boolean | optional | false | whether secret is base64 encoded | |
vault | object | optional | whether vault to be used for secret (secret for HS256/HS512 or public_key and private_key for RS256) storage and retrieval. The plugin by default uses the vault path as kv/apisix/consumer/<consumer name>/jwt-auth for secret retrieval. |
Note: To enable vault integration, first visit the config.yaml update it with your vault server configuration, host address and access token. You can take a look of what APISIX expects from the config.yaml at config-default.yaml under the vault attributes.
This plugin will add /apisix/plugin/jwt/sign
to sign. You may need to use interceptors to protect it.
jwt-auth
optioncurl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "username": "jack", "plugins": { "jwt-auth": { "key": "user-key", "secret": "my-secret-key" } } }'
jwt-auth
uses the HS256
algorithm by default, and if you use the RS256
algorithm, you need to specify the algorithm and configure the public key and private key, as follows:
curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "username": "kerouac", "plugins": { "jwt-auth": { "key": "user-key", "public_key": "-----BEGIN PUBLIC KEY-----\n……\n-----END PUBLIC KEY-----", "private_key": "-----BEGIN RSA PRIVATE KEY-----\n……\n-----END RSA PRIVATE KEY-----", "algorithm": "RS256" } } }'
jwt-auth
plugincurl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "methods": ["GET"], "uri": "/index.html", "plugins": { "jwt-auth": {} }, "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:1980": 1 } } }'
Sometimes, it‘s quite natural in production to have a centralized key management solution like vault where you don’t have to update the APISIX consumer each time some part of your organization changes the signing secret key (secret for HS256/HS512 or public_key and private_key for RS256) and/or for privacy concerns you don't want to use the key through APISIX admin APIs. APISIX got you covered here. The jwt-auth
is capable of referencing keys from vault.
Note: For early version of this integration support, the plugin expects the key name of secrets stored into the vault path is among [ secret
, public_key
, private_key
] to successfully use the key. In future releases, we are going to add the support of referencing custom named keys.
To enable vault compatibility, just add the empty vault object inside the jwt-auth plugin.
curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "username": "jack", "plugins": { "jwt-auth": { "key": "key-1", "vault": {} } } }'
Here the plugin looks up for key secret
inside vault path (<vault.prefix from conf.yaml>/consumer/jack/jwt-auth
) for consumer username jack
mentioned in the consumer config and uses it for subsequent signing and jwt verification. If the key is not found in the same path, the plugin logs error and fails to perform jwt authentication.
curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "username": "kowalski", "plugins": { "jwt-auth": { "key": "rsa-keypair", "algorithm": "RS256", "vault": {} } } }'
The plugin looks up for public_key
and private_key
keys inside vault kv path (<vault.prefix from conf.yaml>/consumer/kowalski/jwt-auth
) for username kowalski
mentioned inside plugin vault configuration. If not found, authentication fails.
curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "username": "rico", "plugins": { "jwt-auth": { "key": "user-key", "algorithm": "RS256", "public_key": "-----BEGIN PUBLIC KEY-----\n……\n-----END PUBLIC KEY-----" "vault": {} } } }'
This plugin uses rsa public key from consumer configuration and uses the private key directly fetched from vault.
You can use APISIX Dashboard to complete the above operations through the web console.
then add jwt-auth plugin in the Consumer page:
jwt-auth
Plugin:$ curl http://127.0.0.1:9080/apisix/plugin/jwt/sign?key=user-key -i HTTP/1.1 200 OK Date: Wed, 24 Jul 2019 10:33:31 GMT Content-Type: text/plain Transfer-Encoding: chunked Connection: keep-alive Server: APISIX web server eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTU2NDA1MDgxMX0.Us8zh_4VjJXF-TmR5f8cif8mBU7SuefPlpxhH0jbPVI
$ curl -G --data-urlencode 'payload={"uid":10000,"uname":"test"}' http://127.0.0.1:9080/apisix/plugin/jwt/sign?key=user-key -i HTTP/1.1 200 OK Date: Wed, 21 Apr 2021 06:43:59 GMT Content-Type: text/plain; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Server: APISIX/2.4 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmFtZSI6InRlc3QiLCJ1aWQiOjEwMDAwLCJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTYxOTA3MzgzOX0.jI9-Rpz1gc3u8Y6lZy8I43RXyCu0nSHANCvfn0YZUCY
$ curl http://127.0.0.1:9080/index.html -i HTTP/1.1 401 Unauthorized ... {"message":"Missing JWT token in request"}
$ curl http://127.0.0.1:9080/index.html -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTU2NDA1MDgxMX0.Us8zh_4VjJXF-TmR5f8cif8mBU7SuefPlpxhH0jbPVI' -i HTTP/1.1 200 OK Content-Type: text/html Content-Length: 13175 ... Accept-Ranges: bytes <!DOCTYPE html> <html lang="cn"> ...
$ curl http://127.0.0.1:9080/index.html?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTU2NDA1MDgxMX0.Us8zh_4VjJXF-TmR5f8cif8mBU7SuefPlpxhH0jbPVI -i HTTP/1.1 200 OK Content-Type: text/html Content-Length: 13175 ... Accept-Ranges: bytes <!DOCTYPE html> <html lang="cn"> ...
$ curl http://127.0.0.1:9080/index.html --cookie jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTU2NDA1MDgxMX0.Us8zh_4VjJXF-TmR5f8cif8mBU7SuefPlpxhH0jbPVI -i HTTP/1.1 200 OK Content-Type: text/html Content-Length: 13175 ... Accept-Ranges: bytes <!DOCTYPE html> <html lang="cn"> ...
When you want to disable the jwt-auth
plugin, it is very simple, you can delete the corresponding json configuration in the plugin configuration, no need to restart the service, it will take effect immediately:
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "methods": ["GET"], "uri": "/index.html", "id": 1, "plugins": {}, "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:1980": 1 } } }'