This is an automated email from the ASF dual-hosted git repository.
membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-apisix.git
The following commit(s) were added to refs/heads/master by this push:
new c91da99 feature(jwt-auth): support base64 secret for `jwt-auth`
plugin. (#1224)
c91da99 is described below
commit c91da997ebf139859a45e17bcdac1f35b34801f5
Author: paoying <[email protected]>
AuthorDate: Wed Apr 8 09:34:14 2020 +0800
feature(jwt-auth): support base64 secret for `jwt-auth` plugin. (#1224)
---
apisix/plugins/jwt-auth.lua | 21 ++++++--
doc/plugins/jwt-auth.md | 1 +
t/plugin/jwt-auth.t | 129 +++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 147 insertions(+), 4 deletions(-)
diff --git a/apisix/plugins/jwt-auth.lua b/apisix/plugins/jwt-auth.lua
index 0669388..4b73580 100644
--- a/apisix/plugins/jwt-auth.lua
+++ b/apisix/plugins/jwt-auth.lua
@@ -18,6 +18,9 @@ local core = require("apisix.core")
local jwt = require("resty.jwt")
local ck = require("resty.cookie")
local consumer = require("apisix.consumer")
+local resty_random = require("resty.random")
+local ngx_encode_base64 = ngx.encode_base64
+local ngx_decode_base64 = ngx.decode_base64
local ipairs = ipairs
local ngx = ngx
local ngx_time = ngx.time
@@ -35,6 +38,10 @@ local schema = {
enum = {"HS256", "HS384", "HS512", "RS256", "ES256"}
},
exp = {type = "integer", minimum = 1},
+ base64_secret = {
+ type = "boolean",
+ default = false
+ }
}
}
@@ -75,7 +82,7 @@ function _M.check_schema(conf)
end
if not conf.secret then
- conf.secret = core.id.gen_uuid_v4()
+ conf.secret = ngx_encode_base64(resty_random.bytes(32, true))
end
if not conf.algorithm then
@@ -114,6 +121,12 @@ local function fetch_jwt_token(ctx)
return val, err
end
+local function get_secret(conf)
+ if conf.base64_secret then
+ return ngx_decode_base64(conf.secret)
+ end
+ return conf.secret
+end
function _M.rewrite(conf, ctx)
local jwt_token, err = fetch_jwt_token(ctx)
@@ -151,7 +164,8 @@ function _M.rewrite(conf, ctx)
end
core.log.info("consumer: ", core.json.delay_encode(consumer))
- jwt_obj = jwt:verify_jwt_obj(consumer.auth_conf.secret, jwt_obj)
+ local auth_secret = get_secret(consumer.auth_conf)
+ jwt_obj = jwt:verify_jwt_obj(auth_secret, jwt_obj)
core.log.info("jwt object: ", core.json.delay_encode(jwt_obj))
if not jwt_obj.verified then
return 401, {message = jwt_obj.reason}
@@ -188,8 +202,9 @@ local function gen_token()
core.log.info("consumer: ", core.json.delay_encode(consumer))
+ local auth_secret = get_secret(consumer.auth_conf)
local jwt_token = jwt:sign(
- consumer.auth_conf.secret,
+ auth_secret,
{
header={
typ = "JWT",
diff --git a/doc/plugins/jwt-auth.md b/doc/plugins/jwt-auth.md
index 4d4e352..ed57175 100644
--- a/doc/plugins/jwt-auth.md
+++ b/doc/plugins/jwt-auth.md
@@ -43,6 +43,7 @@ For more information on JWT, refer to [JWT](https://jwt.io/)
for more informatio
| secret |optional|encryption key. if you do not specify, the value is
auto-generated in the background.|
| algorithm | optional|encryption algorithm. support`HS256`, `HS384`,
`HS512`, `RS256` and `ES256`,`HS256` is default.|
| exp |optional|token's expire time, the unit is second. for example,
5 minutes, need to set the value of 300.( 5 * 60 = 300 )|
+| base64_secret|optional|boolean value to indicate whether secret is base64
encoded, default value is false.|
## How To Enable
diff --git a/t/plugin/jwt-auth.t b/t/plugin/jwt-auth.t
index d910bc2..cad7d3a 100644
--- a/t/plugin/jwt-auth.t
+++ b/t/plugin/jwt-auth.t
@@ -42,7 +42,7 @@ __DATA__
--- request
GET /t
--- response_body_like eval
-qr/{"algorithm":"HS256","secret":"\w+-\w+-\w+-\w+-\w+","exp":86400}/
+qr/{"algorithm":"HS256","secret":"^[a-zA-Z0-9+/]+={0,2}$","exp":86400}/
--- no_error_log
[error]
@@ -327,3 +327,130 @@ code: true body: passed
code: true body: passed
--- no_error_log
[error]
+
+
+
+=== TEST 17: add consumer with username and plugins with base64 secret
+--- 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":
"fo4XKdZ1xSrIZyms4q2BwPrW5lMpls9qqy5tiAk2esc=",
+ "base64_secret": true
+ }
+ }
+ }]],
+ [[{
+ "node": {
+ "value": {
+ "username": "jack",
+ "plugins": {
+ "jwt-auth": {
+ "key": "user-key",
+ "secret":
"fo4XKdZ1xSrIZyms4q2BwPrW5lMpls9qqy5tiAk2esc=",
+ "base64_secret": true
+ }
+ }
+ }
+ },
+ "action": "set"
+ }]]
+ )
+ ngx.status = code
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 18: enable jwt auth plugin with base64 secret
+--- 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": {}
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 19: sign
+--- request
+GET /apisix/plugin/jwt/sign?key=user-key
+--- response_body_like eval
+qr/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\w+.\w+/
+--- no_error_log
+[error]
+
+
+
+=== TEST 20: verify: invalid JWT token
+--- request
+GET
/hello?jwt=invalid-eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTU2Mzg3MDUwMX0.pPNVvh-TQsdDzorRwa-uuiLYiEBODscp9wv0cwD6c68
+--- error_code: 401
+--- response_body
+{"message":"invalid header: invalid-eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"}
+--- no_error_log
+[error]
+
+
+
+=== TEST 21: verify: invalid signature
+--- request
+GET /hello
+--- more_headers
+Authorization: Bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
+--- error_code: 401
+--- response_body
+{"message":"signature mismatch: fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs"}
+--- no_error_log
+[error]
+
+
+
+=== TEST 22: verify: happy path
+--- request
+GET /hello
+--- more_headers
+Authorization: Bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0._kNmXeH1uYVAvApFTONk2Z3Gh-a4XfGrjmqd_ahoOI0
+--- response_body
+hello world
+--- no_error_log
+[error]