This is an automated email from the ASF dual-hosted git repository.
shreemaan-abhishek 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 f7139e2ad4 fix(jwe-decrypt,forward-auth): clear forwarded headers when
skipping (#14096)
f7139e2ad4 is described below
commit f7139e2ad442acc89b36b6a6a92c01bff29e7edd
Author: Shreemaan Abhishek <[email protected]>
AuthorDate: Tue Oct 27 20:22:13 2026 +0800
fix(jwe-decrypt,forward-auth): clear forwarded headers when skipping
(#14096)
---
apisix/plugins/forward-auth.lua | 4 +++
apisix/plugins/jwe-decrypt.lua | 2 ++
docs/en/latest/plugins/forward-auth.md | 2 +-
docs/en/latest/plugins/jwe-decrypt.md | 2 +-
docs/zh/latest/plugins/forward-auth.md | 2 +-
docs/zh/latest/plugins/jwe-decrypt.md | 2 +-
t/plugin/forward-auth3.t | 63 ++++++++++++++++++++++++++++++++++
t/plugin/jwe-decrypt.t | 52 ++++++++++++++++++++++++++++
8 files changed, 125 insertions(+), 4 deletions(-)
diff --git a/apisix/plugins/forward-auth.lua b/apisix/plugins/forward-auth.lua
index d3e965d915..78efc1967f 100644
--- a/apisix/plugins/forward-auth.lua
+++ b/apisix/plugins/forward-auth.lua
@@ -178,6 +178,10 @@ function _M.access(conf, ctx)
local res, err = httpc:request_uri(conf.uri, params)
if not res and conf.allow_degradation then
+ -- drop client-supplied copies of the configured upstream headers
+ for _, header in ipairs(conf.upstream_headers) do
+ core.request.set_header(ctx, header, nil)
+ end
return
elseif not res then
core.log.warn("failed to process forward auth, err: ", err)
diff --git a/apisix/plugins/jwe-decrypt.lua b/apisix/plugins/jwe-decrypt.lua
index 3a7a150a1f..d9bd91e101 100644
--- a/apisix/plugins/jwe-decrypt.lua
+++ b/apisix/plugins/jwe-decrypt.lua
@@ -217,6 +217,8 @@ end
function _M.rewrite(conf, ctx)
-- fetch token and hide credentials if necessary
local jwe_token, err = fetch_jwe_token(conf, ctx)
+ -- only the decrypted plaintext may reach the upstream in forward_header
+ core.request.set_header(ctx, conf.forward_header, nil)
if not jwe_token then
-- If true, throw a 403 error if JWE token is missing from the request.
-- If false, do not throw an error when JWE token is not found.
diff --git a/docs/en/latest/plugins/forward-auth.md
b/docs/en/latest/plugins/forward-auth.md
index 1946e4ecae..d099e54c1c 100644
--- a/docs/en/latest/plugins/forward-auth.md
+++ b/docs/en/latest/plugins/forward-auth.md
@@ -72,7 +72,7 @@ If your authorization service decides based on the URI that
the Upstream service
| request_method | string | False | GET | `GET` or `POST`
| HTTP method APISIX uses to send requests to the external authorization
service. When set to `POST`, APISIX will send POST requests along with the
request body to the external authorization service. If the authorization
decision depends on request parameters from a POST body, it is recommended to
extract the necessary fields using `$post_arg.*` and pass them via the
`extra_headers` field instead. |
| max_req_body_size | integer | False | 67108864 | >= 1
| Maximum request body size in bytes buffered and forwarded to the
external authorization service when `request_method` is `POST`. Requests whose
body exceeds this limit are rejected with `413`. Prevents unbounded memory
buffering of large request bodies. |
| request_headers | array | False | |
| Client request headers that should be forwarded to the external
authorization service. If not configured, only headers added by APISIX are
forwarded, such as `X-Forwarded-*`.
|
-| upstream_headers | array | False | |
| External authorization service response headers that should be
forwarded to the Upstream service. If not configured, no headers are forwarded
to the Upstream service.
|
+| upstream_headers | array | False | |
| External authorization service response headers that should be
forwarded to the Upstream service. If not configured, no headers are forwarded
to the Upstream service. Client-supplied values of these headers are always
removed. |
| client_headers | array | False | |
| External authorization service response headers that should be
forwarded to the client when authentication fails. If not configured, no
headers are forwarded to the client.
|
| extra_headers | object | False | |
| Additional headers to send to the authorization service. Support [NGINX
variables](https://nginx.org/en/docs/http/ngx_http_core_module.html) in values.
|
| timeout | integer | False | 3000 | between 1 and 60000
inclusive | Timeout for the external authorization service HTTP call in
milliseconds.
|
diff --git a/docs/en/latest/plugins/jwe-decrypt.md
b/docs/en/latest/plugins/jwe-decrypt.md
index 135090753d..07144cf31e 100644
--- a/docs/en/latest/plugins/jwe-decrypt.md
+++ b/docs/en/latest/plugins/jwe-decrypt.md
@@ -68,7 +68,7 @@ The decrypted plaintext is forwarded in a request header. For
sensitive plaintex
| Name | Type | Required | Default | Valid values |
Description
|
| -------------- | ------- | -------- | ------------- | ------------ |
---------------------------------------------------------------------------------------------------------------------------------
|
| header | string | True | Authorization | | The
header to get the token from.
|
-| forward_header | string | True | Authorization | | Name of
the header that passes the plaintext to the Upstream.
|
+| forward_header | string | True | Authorization | | Name of
the header that passes the plaintext to the Upstream. Any client-supplied value
of this header is removed. |
| strict | boolean | False | true | | If
true, return a 403 error when the JWE token is missing. If false, continue when
the token is not found. |
## Examples
diff --git a/docs/zh/latest/plugins/forward-auth.md
b/docs/zh/latest/plugins/forward-auth.md
index 6b7117858e..d0983ef4af 100644
--- a/docs/zh/latest/plugins/forward-auth.md
+++ b/docs/zh/latest/plugins/forward-auth.md
@@ -71,7 +71,7 @@ import TabItem from '@theme/TabItem';
| ssl_verify | boolean | 否 | true |
| 如果为 true,则验证授权服务的 SSL 证书。
|
| request_method | string | 否 | GET | `GET` 或 `POST`
| APISIX 向外部授权服务发送请求时使用的 HTTP 方法。当设置为 `POST` 时,APISIX 将连同请求体一起向外部授权服务发送 POST
请求。如果授权决策依赖 POST 正文中的请求参数,建议使用 `$post_arg.*` 提取必要字段并通过 `extra_headers`
字段传递,而不是发送完整请求体。 |
| request_headers | array | 否 | |
| 需要转发给外部授权服务的客户端请求头。如果未配置,则只转发 APISIX 添加的请求头,例如 `X-Forwarded-*`。
|
-| upstream_headers | array | 否 | |
| 认证通过时,需要转发到 Upstream 服务的外部授权服务响应头。如果未配置,则不转发任何请求头。
|
+| upstream_headers | array | 否 | |
| 认证通过时,需要转发到 Upstream 服务的外部授权服务响应头。如果未配置,则不转发任何请求头。客户端传入的同名请求头总会被移除。
|
| client_headers | array | 否 | |
| 认证失败时,需要转发给客户端的外部授权服务响应头。如果未配置,则不转发任何响应头。
|
| extra_headers | object | 否 | |
| 发送给授权服务的额外请求头,支持在值中使用 [NGINX
变量](https://nginx.org/en/docs/http/ngx_http_core_module.html)。
|
| timeout | integer | 否 | 3000 | 1 到 60000 之间(含) |
外部授权服务 HTTP 调用的超时时间(毫秒)。
|
diff --git a/docs/zh/latest/plugins/jwe-decrypt.md
b/docs/zh/latest/plugins/jwe-decrypt.md
index b0cbe51e96..4458873547 100644
--- a/docs/zh/latest/plugins/jwe-decrypt.md
+++ b/docs/zh/latest/plugins/jwe-decrypt.md
@@ -56,7 +56,7 @@ import TabItem from '@theme/TabItem';
| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述
|
| -------------- | ------- | ------ | ------------- | ------ |
----------------------------------------------------------------------------------------------
|
| header | string | 是 | Authorization | | 用于获取令牌的请求头。
|
-| forward_header | string | 是 | Authorization | | 传递明文给上游的请求头名称。
|
+| forward_header | string | 是 | Authorization | |
传递明文给上游的请求头名称。客户端传入的同名请求头会被移除。 |
| strict | boolean | 否 | true | | 如果为 true,当请求中缺少
JWE 令牌时抛出 403 错误。如果为 false,当找不到 JWE 令牌时不抛出错误。 |
## 使用示例
diff --git a/t/plugin/forward-auth3.t b/t/plugin/forward-auth3.t
index 1bb32c7aaa..afd12d45e7 100644
--- a/t/plugin/forward-auth3.t
+++ b/t/plugin/forward-auth3.t
@@ -105,3 +105,66 @@ GET /hello
X-User-ID: injected-value
--- response_body_unlike eval
qr/x-user-id/
+
+
+
+=== TEST 3: setup route with an unavailable auth server and allow_degradation
+--- config
+ location /t {
+ content_by_lua_block {
+ local data = {
+ {
+ url = "/apisix/admin/routes/crashed-auth",
+ data = [[{
+ "plugins": {
+ "serverless-pre-function": {
+ "phase": "rewrite",
+ "functions" : ["return function()
require(\"apisix.core\").response.exit(444); end"]
+ }
+ },
+ "upstream_id": "u1",
+ "uri": "/crashed-auth"
+ }]],
+ },
+ {
+ url = "/apisix/admin/routes/2",
+ data = [[{
+ "plugins": {
+ "forward-auth": {
+ "uri": "http://127.0.0.1:1984/crashed-auth",
+ "upstream_headers": ["X-User-ID"],
+ "allow_degradation": true
+ },
+ "serverless-post-function": {
+ "phase": "access",
+ "functions": [
+ "return function(conf, ctx) local core =
require(\"apisix.core\"); core.response.exit(200, core.request.headers(ctx));
end"
+ ]
+ }
+ },
+ "upstream_id": "u1",
+ "uri": "/degraded"
+ }]],
+ }
+ }
+
+ local t = require("lib.test_admin").test
+
+ for _, data in ipairs(data) do
+ local code, body = t(data.url, ngx.HTTP_PUT, data.data)
+ ngx.say(body)
+ end
+ }
+ }
+--- response_body eval
+"passed\n" x 2
+
+
+
+=== TEST 4: client-supplied upstream_headers are cleared when the auth server
is unavailable
+--- request
+GET /degraded
+--- more_headers
+X-User-ID: injected-value
+--- response_body_unlike eval
+qr/x-user-id/
diff --git a/t/plugin/jwe-decrypt.t b/t/plugin/jwe-decrypt.t
index deb68a3fb2..cdf843b217 100644
--- a/t/plugin/jwe-decrypt.t
+++ b/t/plugin/jwe-decrypt.t
@@ -929,3 +929,55 @@ status: 200
}
--- response_body
status: 400 body: {"message":"unsupported alg or enc in JWE token"}
+
+
+
+=== TEST 38: enable jwe-decrypt with strict=false and a separate forward_header
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/12',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "jwe-decrypt": {
+ "header": "Authorization",
+ "forward_header": "X-Decrypted-Auth",
+ "strict": false
+ },
+ "serverless-post-function": {
+ "phase": "access",
+ "functions": [
+ "return function(conf, ctx) local core =
require(\"apisix.core\"); core.response.exit(200, core.request.headers(ctx));
end"
+ ]
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello-forward-header"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 39: client-supplied forward_header is dropped when the token is
missing
+--- request
+GET /hello-forward-header
+--- more_headers
+X-Decrypted-Auth: client-value
+--- response_body_unlike eval
+qr/x-decrypted-auth/