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]

Reply via email to