Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support hide credentials for jwt-auth plugin #8206

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d1830f3
doc update: fix hide_credentials description
Oct 30, 2022
2c7d410
feat: support jwt-auth of hidding sensitive param
pixeldin Oct 30, 2022
51eb733
Merge branch 'master' of https://github.com/apache/apisix into jwt-au…
pixeldin Oct 30, 2022
f0ffec8
doc: update plugin param description for EN-US
pixeldin Oct 30, 2022
51dea0f
doc: update plugin(jwt-auth) param description for EN-US
pixeldin Oct 31, 2022
7ee2cd4
lint: code reformat and reindex
pixeldin Oct 31, 2022
06c2970
Update t/plugin/jwt-auth3.t
pixeldin Oct 31, 2022
3440bfe
Update t/plugin/jwt-auth3.t
pixeldin Oct 31, 2022
e9519b8
code reformat
pixeldin Oct 31, 2022
8a24d82
format test file about trailing whitespace
pixeldin Oct 31, 2022
493b24c
adjust the hide credentials logic code and update cookie setting way
pixeldin Nov 1, 2022
41b52b2
Merge branch 'master' of https://github.com/apache/apisix into jwt-au…
pixeldin Nov 1, 2022
6006c52
License Header Addition of test file
pixeldin Nov 2, 2022
64b6dde
rewrite cookie updating way and import httpbin for testing related pa…
pixeldin Nov 4, 2022
dac50b5
Merge branch 'master' of https://github.com/apache/apisix into jwt-au…
pixeldin Nov 4, 2022
da2f64b
fix expected final newline
pixeldin Nov 5, 2022
5179af6
adjusting unit test and hiding credential in cookie with regex pattern
pixeldin Nov 7, 2022
fa9081c
Merge branch 'master' of https://github.com/apache/apisix into jwt-au…
pixeldin Nov 7, 2022
f0d11f7
Update docs/zh/latest/plugins/jwt-auth.md
pixeldin Nov 8, 2022
fc1eaf9
reset cookie val with table.concat() way and reformat test file
pixeldin Nov 8, 2022
c09dfc3
Merge branch 'jwt-auth-plugin-supporting-hide-credentials' of https:/…
pixeldin Nov 8, 2022
3a42895
use Lua local func tools for string and table
pixeldin Nov 9, 2022
b1c6fa0
reformat test file about jwt-auth
pixeldin Nov 9, 2022
cddc27f
use ngx.re specification as cookie match way
pixeldin Nov 9, 2022
3c8a9e1
consider abnormal case and reformat test
pixeldin Nov 10, 2022
a55846a
fix trim trailing whitespace
pixeldin Nov 10, 2022
284c428
Update apisix/plugins/jwt-auth.lua
pixeldin Nov 11, 2022
b5bc8c7
adjust test file and print cover cookie case
pixeldin Nov 11, 2022
b2a1e7d
define default block for test file
pixeldin Nov 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions apisix/plugins/jwt-auth.lua
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ local schema = {
cookie = {
type = "string",
default = "jwt"
},
hide_credentials = {
type = "boolean",
default = false
}
},
}
Expand Down Expand Up @@ -357,8 +361,31 @@ local function algorithm_handler(consumer, method_only)
end
end

local function set_our_cookie(name, val)
core.response.add_header("Set-Cookie", name .. "=" .. val)
pixeldin marked this conversation as resolved.
Show resolved Hide resolved
end


function _M.rewrite(conf, ctx)
local from_header = true
local header_key = core.request.header(ctx, conf.header)

local from_query = true

if not header_key then
from_header = false
local uri_args = core.request.get_uri_args(ctx) or {}
header_key = uri_args[conf.query]
if not header_key then
from_query = false
local cookie = ctx.var["cookie_" .. conf.cookie]
if not cookie then
core.log.info("failed to fetch JWT token")
return 401, {message = "Missing JWT token in request"}
end
end
end
pixeldin marked this conversation as resolved.
Show resolved Hide resolved
pixeldin marked this conversation as resolved.
Show resolved Hide resolved

local jwt_token, err = fetch_jwt_token(conf, ctx)
if not jwt_token then
core.log.info("failed to fetch JWT token: ", err)
Expand Down Expand Up @@ -407,6 +434,27 @@ function _M.rewrite(conf, ctx)
return 401, {message = "failed to verify jwt"}
end

-- check for hiding `Authorization` request header if `hide_credentials` is `true`
if conf.hide_credentials then
-- hide sensitive field
if from_header then
-- hide for header
local temp_token = core.request.header(ctx, conf.header)
core.request.set_header(ctx, conf.header, nil)


pixeldin marked this conversation as resolved.
Show resolved Hide resolved
elseif from_query then
-- hide for query
local args = core.request.get_uri_args(ctx)
args[conf.query] = nil
core.request.set_uri_args(ctx, args)

else
-- hide for cookie
set_our_cookie(conf.cookie, "deleted; Max-Age=0")
pixeldin marked this conversation as resolved.
Show resolved Hide resolved
end
end

consumer_mod.attach_consumer(ctx, consumer, consumer_conf)
core.log.info("hit jwt-auth rewrite")
end
Expand Down
2 changes: 1 addition & 1 deletion docs/en/latest/plugins/basic-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ For Route:

| Name | Type | Required | Default | Description |
|------------------|---------|----------|---------|------------------------------------------------------------------------|
| hide_credentials | boolean | False | false | Set to true to pass the authorization request headers to the Upstream. |
| hide_credentials | boolean | False | false | Set to true will not pass the authorization request headers to the Upstream. |

## Enabling the Plugin

Expand Down
1 change: 1 addition & 0 deletions docs/en/latest/plugins/jwt-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ For Route:
| 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.|

## API

Expand Down
2 changes: 1 addition & 1 deletion docs/zh/latest/plugins/basic-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Route 端:

| 名称 | 类型 | 必选项 | 默认值 | 描述 |
| ---------------- | ------- | ------ | ------ | --------------------------------------------------------------- |
| hide_credentials | boolean | 否 | false | 该参数设置为 `true` 时,则会将 Authorization 请求头传递给 Upstream。|
| hide_credentials | boolean | 否 | false | 该参数设置为 `true` 时,则不会将 Authorization 请求头传递给 Upstream。|

## 启用插件

Expand Down
1 change: 1 addition & 0 deletions docs/zh/latest/plugins/jwt-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Route 端:
| header | string | 否 | authorization | 设置我们从哪个 header 获取 token。 |
| query | string | 否 | jwt | 设置我们从哪个 query string 获取 token,优先级低于 header。 |
| cookie | string | 否 | jwt | 设置我们从哪个 cookie 获取 token,优先级低于 query。 |
| hide_credentials | boolean | 否 | false | 该参数设置为 `true` 时,则不会将含有认证信息的 header\query\cookie string 传递给 Upstream。|
pixeldin marked this conversation as resolved.
Show resolved Hide resolved

## 接口

Expand Down
278 changes: 278 additions & 0 deletions t/plugin/jwt-auth3.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
use t::APISIX 'no_plan';

repeat_each(1);
no_long_string();
no_root_location();
no_shuffle();

add_block_preprocessor(sub {
my ($block) = @_;

if ((!defined $block->error_log) && (!defined $block->no_error_log)) {
$block->set_value("no_error_log", "[error]");
}

if (!defined $block->request) {
$block->set_value("request", "GET /t");
}
pixeldin marked this conversation as resolved.
Show resolved Hide resolved
});

run_tests;

__DATA__

=== TEST 1: add consumer with username and plugins
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers',
ngx.HTTP_PUT,
[[{
"username": "jack",
"plugins": {
"jwt-auth": {
"key": "user-key",
"secret": "my-secret-key"
}
}
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- response_body
passed



=== TEST 2: enable jwt auth plugin using admin api with custom parameter
--- 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": {
"header": "jwt-header",
"query": "jwt-query",
"cookie": "jwt-cookie",
"hide_credentials": false
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/echo"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
pixeldin marked this conversation as resolved.
Show resolved Hide resolved
--- response_body
passed



=== TEST 3: verify (in header) with not hidden auth
pixeldin marked this conversation as resolved.
Show resolved Hide resolved
--- request
GET /echo
--- more_headers
jwt-header: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
--- response_headers
jwt-header: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs



=== TEST 4: verify (in cookie) with not hidden auth
pixeldin marked this conversation as resolved.
Show resolved Hide resolved
--- request
GET /echo
--- more_headers
Cookie: jwt-cookie=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
--- response_headers
Cookie: jwt-cookie=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs



=== TEST 5: enable jwt auth plugin using admin api with not hide
# the `proxy-rewrite` play role as upstream to check sensitive param
pixeldin marked this conversation as resolved.
Show resolved Hide resolved
pixeldin marked this conversation as resolved.
Show resolved Hide resolved
--- 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": {
"header": "jwt-header",
"query": "jwt-query",
"cookie": "jwt-cookie",
"hide_credentials": false
},
"proxy-rewrite": {
"uri": "/plugin_proxy_rewrite_args"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/echo"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed



=== TEST 6: verify (in query) not hidden auth
--- request
GET /echo?foo=bar&hello=world&jwt-query=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
--- response_body
uri: /plugin_proxy_rewrite_args
foo: bar
hello: world
jwt-query: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
--- no_error_log
[error]



=== TEST 7: enable jwt auth plugin using admin api with hide auth
--- 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": {
"header": "jwt-header",
"query": "jwt-query",
"cookie": "jwt-cookie",
"hide_credentials": true
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/echo"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
pixeldin marked this conversation as resolved.
Show resolved Hide resolved
--- response_body
passed



=== TEST 8: verify (in header) with hidden auth
--- request
GET /echo
--- more_headers
jwt-header: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
--- response_headers
!jwt-header



=== TEST 9: verify (in cookie) with hidden auth
--- request
GET /echo
--- more_headers
Cookie: jwt-cookie=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs; foo=bar
--- response_headers
Set-Cookie: jwt-cookie=deleted; Max-Age=0

=== TEST 10: enable jwt auth plugin using admin api with hidden auth
# the `proxy-rewrite` play role as upstream to check sensitive param
--- 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": {
"header": "jwt-header",
"query": "jwt-query",
"cookie": "jwt-cookie",
"hide_credentials": true
},
"proxy-rewrite": {
"uri": "/plugin_proxy_rewrite_args"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/echo"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed



=== TEST 11: verify (in query) with hidden auth
--- request
GET /echo?foo=bar&hello=world&jwt-query=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
--- response_body
uri: /plugin_proxy_rewrite_args
foo: bar
hello: world
--- no_error_log
[error]