Skip to content

Commit

Permalink
feat: jwt-plugin support custom parameters (#6561)
Browse files Browse the repository at this point in the history
Co-authored-by: 高亮亮 <gll287546@alibaba-inc.com>
  • Loading branch information
liangliang4ward and 高亮亮 authored Mar 14, 2022
1 parent ddb884c commit 6182ba9
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 6 deletions.
25 changes: 19 additions & 6 deletions apisix/plugins/jwt-auth.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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"}
Expand Down
10 changes: 10 additions & 0 deletions docs/en/latest/plugins/jwt-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -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. |
Expand All @@ -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.
Expand Down
10 changes: 10 additions & 0 deletions docs/zh/latest/plugins/jwt-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ title: jwt-auth

## 属性

consumer 端配置:

| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
| :------------ | :------ | :----- | :------ | :-------------------------- | :------------------------------------------------------------------------------------------------------------ |
| key | string | 必须 | | | 不同的 `consumer` 对象应有不同的值,它应当是唯一的。不同 consumer 使用了相同的 `key` ,将会出现请求匹配异常。 |
Expand All @@ -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) 插件来暴露它。
Expand Down
149 changes: 149 additions & 0 deletions t/plugin/jwt-auth2.t
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 6182ba9

Please sign in to comment.