You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2022/03/14 03:43:45 UTC

[apisix] branch master updated: feat: jwt-plugin support custom parameters (#6561)

This is an automated email from the ASF dual-hosted git repository.

spacewander 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 6182ba9  feat: jwt-plugin support custom parameters (#6561)
6182ba9 is described below

commit 6182ba9f962c4352456b4b65cec3d69354737341
Author: Gaoll <lx...@126.com>
AuthorDate: Mon Mar 14 11:43:35 2022 +0800

    feat: jwt-plugin support custom parameters (#6561)
    
    Co-authored-by: 高亮亮 <gl...@alibaba-inc.com>
---
 apisix/plugins/jwt-auth.lua        |  25 +++++--
 docs/en/latest/plugins/jwt-auth.md |  10 +++
 docs/zh/latest/plugins/jwt-auth.md |  10 +++
 t/plugin/jwt-auth2.t               | 149 +++++++++++++++++++++++++++++++++++++
 4 files changed, 188 insertions(+), 6 deletions(-)

diff --git a/apisix/plugins/jwt-auth.lua b/apisix/plugins/jwt-auth.lua
index d1282cd..eea7159 100644
--- a/apisix/plugins/jwt-auth.lua
+++ b/apisix/plugins/jwt-auth.lua
@@ -36,7 +36,20 @@ local lrucache = core.lrucache.new({
 
 local schema = {
     type = "object",
-    properties = {},
+    properties = {
+        header = {
+            type = "string",
+            default = "authorization"
+        },
+        query = {
+            type = "string",
+            default = "jwt"
+        },
+        cookie = {
+            type = "string",
+            default = "jwt"
+        }
+    },
 }
 
 local consumer_schema = {
@@ -171,8 +184,8 @@ function _M.check_schema(conf, schema_type)
 end
 
 
-local function fetch_jwt_token(ctx)
-    local token = core.request.header(ctx, "authorization")
+local function fetch_jwt_token(conf, ctx)
+    local token = core.request.header(ctx, conf.header)
     if token then
         local prefix = sub_str(token, 1, 7)
         if prefix == 'Bearer ' or prefix == 'bearer ' then
@@ -182,12 +195,12 @@ local function fetch_jwt_token(ctx)
         return token
     end
 
-    token = ctx.var.arg_jwt
+    token = ctx.var["arg_" .. conf.query]
     if token then
         return token
     end
 
-    local val = ctx.var.cookie_jwt
+    local val = ctx.var["cookie_" .. conf.cookie]
     if not val then
         return nil, "JWT not found in cookie"
     end
@@ -339,7 +352,7 @@ end
 
 
 function _M.rewrite(conf, ctx)
-    local jwt_token, err = fetch_jwt_token(ctx)
+    local jwt_token, err = fetch_jwt_token(conf, ctx)
     if not jwt_token then
         core.log.info("failed to fetch JWT token: ", err)
         return 401, {message = "Missing JWT token in request"}
diff --git a/docs/en/latest/plugins/jwt-auth.md b/docs/en/latest/plugins/jwt-auth.md
index a026ce8..5fe10f3 100644
--- a/docs/en/latest/plugins/jwt-auth.md
+++ b/docs/en/latest/plugins/jwt-auth.md
@@ -33,6 +33,8 @@ For more information on JWT, refer to [JWT](https://jwt.io/) for more informatio
 
 ## Attributes
 
+For consumer side:
+
 | Name          | Type    | Requirement | Default | Valid                       | Description                                                                                                                                      |
 |:--------------|:--------|:------------|:--------|:----------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------|
 | key           | string  | required    |         |                             | different `consumer` have different value, it's unique. different `consumer` use the same `key`, and there will be a request matching exception. |
@@ -46,6 +48,14 @@ For more information on JWT, refer to [JWT](https://jwt.io/) for more informatio
 
 **Note**: To enable vault integration, first visit the [config.yaml](https://github.com/apache/apisix/blob/master/conf/config.yaml) update it with your vault server configuration, host address and access token. You can take a look of what APISIX expects from the config.yaml at [config-default.yaml](https://github.com/apache/apisix/blob/master/conf/config-default.yaml) under the vault attributes.
 
+For route side:
+
+| Name | Type   | Requirement | Default | Valid | Description                                                                  |
+| ---- | ------ | ----------- | ------- | ----- | ---------------------------------------------------------------------------- |
+| header  | string | optional    | authorization        |       | the header we get the token from |
+| query   | string | optional    | jwt        |       | the query string we get the token from, which priority is lower than header |
+| cookie | string | optional    | jwt |       | the cookie we get the token from, which priority is lower than querystring |
+
 ## API
 
 This plugin will add `/apisix/plugin/jwt/sign` to sign.
diff --git a/docs/zh/latest/plugins/jwt-auth.md b/docs/zh/latest/plugins/jwt-auth.md
index 37782b5..55644f4 100644
--- a/docs/zh/latest/plugins/jwt-auth.md
+++ b/docs/zh/latest/plugins/jwt-auth.md
@@ -44,6 +44,8 @@ title: jwt-auth
 
 ## 属性
 
+consumer 端配置:
+
 | 名称          | 类型    | 必选项 | 默认值  | 有效值                      | 描述                                                                                                          |
 | :------------ | :------ | :----- | :------ | :-------------------------- | :------------------------------------------------------------------------------------------------------------ |
 | key           | string  | 必须   |         |                             | 不同的 `consumer` 对象应有不同的值,它应当是唯一的。不同 consumer 使用了相同的 `key` ,将会出现请求匹配异常。 |
@@ -57,6 +59,14 @@ title: jwt-auth
 
 **注意**: 要启用 Vault 集成,首先访问 [config.yaml](https://github.com/apache/apisix/blob/master/conf/config.yaml),更新您的 Vault 服务器配置、主机地址和访问令牌。您可以在 [config-default.yaml](https://github.com/apache/apisix/blob/master/conf/config-default.yaml) 中 vault 属性下查看 APISIX 的默认配置。
 
+router 端配置:
+
+| 名称 | 类型   | 必选项 | 默认值 | 有效值 | 描述                                                                                                          |
+| ---- | ------ | ------ | ------ | ------ | ------------------------------------------------------------------------------------------------------------- |
+| header  | string | 可选| authorization |        | 设置我们从哪个 header 获取 token。 |
+| query  | string | 可选 | jwt |        | 设置我们从哪个 query string 获取 token,优先级低于header |
+| cookie  | string | 可选 | jwt |        | 设置我们从哪个 cookie 获取 token,优先级低于query |
+
 ## 接口
 
 插件会增加 `/apisix/plugin/jwt/sign` 这个接口,需要通过 [public-api](../../../en/latest/plugins/public-api.md) 插件来暴露它。
diff --git a/t/plugin/jwt-auth2.t b/t/plugin/jwt-auth2.t
new file mode 100644
index 0000000..a6c6f31
--- /dev/null
+++ b/t/plugin/jwt-auth2.t
@@ -0,0 +1,149 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+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");
+    }
+});
+
+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"
+                        }
+                    },
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/hello"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- response_body
+passed
+
+
+
+=== TEST 3: verify (in header)
+--- request
+GET /hello
+--- more_headers
+jwt-header: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
+--- response_body
+hello world
+
+
+
+=== TEST 4: verify (in cookie)
+--- request
+GET /hello
+--- more_headers
+Cookie: jwt-cookie=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
+--- response_body
+hello world
+
+
+
+=== TEST 5: verify (in query)
+--- request
+GET /hello?jwt-query=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
+--- response_body
+hello world
+
+
+
+=== TEST 6: verify (in header without Bearer)
+--- request
+GET /hello
+--- more_headers
+jwt-header: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
+--- response_body
+hello world
+
+
+
+=== TEST 7: verify (in header with bearer)
+--- request
+GET /hello
+--- more_headers
+jwt-header: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0.fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs
+--- response_body
+hello world