This is an automated email from the ASF dual-hosted git repository.
juzhiyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 381595e9e feat(jwt-auth): store JWT in the request context (#11675)
381595e9e is described below
commit 381595e9e21482cdd1dab6ef73a2b5644c21375c
Author: Michele Righi <[email protected]>
AuthorDate: Wed Mar 5 08:02:28 2025 +0100
feat(jwt-auth): store JWT in the request context (#11675)
---
apisix/plugins/jwt-auth.lua | 8 +++
docs/en/latest/plugins/jwt-auth.md | 15 ++---
docs/zh/latest/plugins/jwt-auth.md | 1 +
t/plugin/jwt-auth4.t | 120 +++++++++++++++++++++++++++++++++++++
4 files changed, 137 insertions(+), 7 deletions(-)
diff --git a/apisix/plugins/jwt-auth.lua b/apisix/plugins/jwt-auth.lua
index 2c00b6bf7..b61d82df3 100644
--- a/apisix/plugins/jwt-auth.lua
+++ b/apisix/plugins/jwt-auth.lua
@@ -56,6 +56,10 @@ local schema = {
default = "key",
minLength = 1,
},
+ store_in_ctx = {
+ type = "boolean",
+ default = false
+ },
anonymous_consumer = schema_def.anonymous_consumer_schema,
},
}
@@ -295,6 +299,10 @@ local function find_consumer(conf, ctx)
return nil, nil, "failed to verify jwt"
end
+ if conf.store_in_ctx then
+ ctx.jwt_auth_payload = jwt_obj.payload
+ end
+
return consumer, consumer_conf
end
diff --git a/docs/en/latest/plugins/jwt-auth.md
b/docs/en/latest/plugins/jwt-auth.md
index 38fab4e87..f52d3cec5 100644
--- a/docs/en/latest/plugins/jwt-auth.md
+++ b/docs/en/latest/plugins/jwt-auth.md
@@ -52,13 +52,14 @@ NOTE: `encrypt_fields = {"secret"}` is also defined in the
schema, which means t
For Route:
-| Name | Type | Required | Default | 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 | Set to true will not
pass the authorization request of header\query\cookie to the Upstream. |
-| key_claim_name | string | False | key | The name of the JWT
claim that contains the user key (corresponds to Consumer's key attribute). |
+| Name | Type | Required | Default | 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 | Set to true will not
pass the authorization request of header\query\cookie to the Upstream.
|
+| key_claim_name | string | False | key | The name of the JWT
claim that contains the user key (corresponds to Consumer's key attribute).
|
+| store_in_ctx | boolean | False | false | Set to true will
store the JWT payload in the request context (`ctx.jwt_auth_payload`). This
allows lower-priority plugins that run afterwards on the same request to
retrieve and use the JWT token. |
You can implement `jwt-auth` with [HashiCorp
Vault](https://www.vaultproject.io/) to store and fetch secrets and RSA keys
pairs from its [encrypted KV
engine](https://developer.hashicorp.com/vault/docs/secrets/kv) using the
[APISIX Secret](../terminology/secret.md) resource.
diff --git a/docs/zh/latest/plugins/jwt-auth.md
b/docs/zh/latest/plugins/jwt-auth.md
index 6c848aa3d..0111e9e03 100644
--- a/docs/zh/latest/plugins/jwt-auth.md
+++ b/docs/zh/latest/plugins/jwt-auth.md
@@ -59,6 +59,7 @@ Route 端:
| cookie | string | 否 | jwt | 设置我们从哪个 cookie 获取 token,优先级低于
query。 |
| hide_credentials | boolean | 否 | false | 该参数设置为 `true` 时,则不会将含有认证信息的
header\query\cookie 传递给 Upstream。|
| key_claim_name | string | 否 | key | 包含用户密钥(对应消费者的密钥属性)的 JWT
声明的名称。|
+| store_in_ctx | boolean | 否 | false | 设置为 `true` 将会将 JWT 负载存储在请求上下文
(`ctx.jwt_auth_payload`) 中。这允许在同一请求上随后运行的低优先级插件检索和使用 JWT 令牌。 |
您可以使用 [HashiCorp Vault](https://www.vaultproject.io/) 实施 `jwt-auth`,以从其[加密的 KV
引擎](https://developer.hashicorp.com/vault/docs/secrets/kv) 使用 [APISIX
Secret](../terminology/secret.md) 资源。
diff --git a/t/plugin/jwt-auth4.t b/t/plugin/jwt-auth4.t
index 48fbc5de1..333b26166 100644
--- a/t/plugin/jwt-auth4.t
+++ b/t/plugin/jwt-auth4.t
@@ -230,3 +230,123 @@ qr/\\"secret\\" validation failed: string too short,
expected at least 1, got 0/
--- error_code: 400
--- response_body eval
qr/\\"key\\" validation failed: string too short, expected at least 1, got 0/
+
+
+
+=== TEST 6: store_in_ctx disabled
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "jwt-auth": {},
+ "serverless-post-function": {
+ "phase": "rewrite",
+ "functions": [
+ "return function(conf, ctx)
+ if ctx.jwt_auth_payload then
+ ngx.status = 200
+ ngx.say(\"JWT found in ctx. Payload key:
\" .. ctx.jwt_auth_payload.key)
+ return ngx.exit(200)
+ else
+ ngx.status = 401
+ ngx.say(\"JWT not found in ctx.\")
+ return ngx.exit(401)
+ end
+ end"
+ ]
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/jwt-auth-no-ctx"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 7: verify store_in_ctx disabled (header with bearer)
+--- request
+GET /jwt-auth-no-ctx
+--- more_headers
+Authorization: bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsIm5iZiI6MTcyNzI3NDk4M30.N6ebc4U5ms976pwKZ_iQ88w_uJKqUVNtTYZ_nXhRpWo
+--- error_code: 401
+--- response_body
+JWT not found in ctx.
+
+
+
+=== TEST 8: store_in_ctx enabled
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/2',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "jwt-auth": {
+ "store_in_ctx": true
+ },
+ "serverless-post-function": {
+ "phase": "rewrite",
+ "functions": [
+ "return function(conf, ctx)
+ if ctx.jwt_auth_payload then
+ ngx.status = 200
+ ngx.say(\"JWT found in ctx. Payload key:
\" .. ctx.jwt_auth_payload.key)
+ return ngx.exit(200)
+ else
+ ngx.status = 401
+ ngx.say(\"JWT not found in ctx.\")
+ return ngx.exit(401)
+ end
+ end"
+ ]
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/jwt-auth-ctx"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 9: verify store_in_ctx enabled (header with bearer)
+--- request
+GET /jwt-auth-ctx
+--- more_headers
+Authorization: bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsIm5iZiI6MTcyNzI3NDk4M30.N6ebc4U5ms976pwKZ_iQ88w_uJKqUVNtTYZ_nXhRpWo
+--- error_code: 200
+--- response_body
+JWT found in ctx. Payload key: user-key