diff --git a/apisix/plugins/jwt-auth.lua b/apisix/plugins/jwt-auth.lua index b61d82df3df9..5b838d91eefc 100644 --- a/apisix/plugins/jwt-auth.lua +++ b/apisix/plugins/jwt-auth.lua @@ -17,11 +17,9 @@ local core = require("apisix.core") local jwt = require("resty.jwt") local consumer_mod = require("apisix.consumer") -local resty_random = require("resty.random") local new_tab = require ("table.new") local auth_utils = require("apisix.utils.auth") -local ngx_encode_base64 = ngx.encode_base64 local ngx_decode_base64 = ngx.decode_base64 local ngx = ngx local sub_str = string.sub @@ -144,8 +142,9 @@ function _M.check_schema(conf, schema_type) return false, err end - if conf.algorithm ~= "RS256" and conf.algorithm ~= "ES256" and not conf.secret then - conf.secret = ngx_encode_base64(resty_random.bytes(32, true)) + if (conf.algorithm == "HS256" or conf.algorithm == "HS512") and not conf.secret then + return false, "property \"secret\" is required ".. + "when \"algorithm\" is \"HS256\" or \"HS512\"" elseif conf.base64_secret then if ngx_decode_base64(conf.secret) == nil then return false, "base64_secret required but the secret is not in base64 format" diff --git a/docs/en/latest/plugins/jwt-auth.md b/docs/en/latest/plugins/jwt-auth.md index 36bac34e0be4..4434658c56cd 100644 --- a/docs/en/latest/plugins/jwt-auth.md +++ b/docs/en/latest/plugins/jwt-auth.md @@ -47,7 +47,7 @@ For Consumer/Credential: | Name | Type | Required | Default | Valid values | Description | |---------------|---------|-------------------------------------------------------|---------|-----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | key | string | True | | non-empty | Unique key for a Consumer. | -| secret | string | False | | non-empty | Shared key used to sign and verify the JWT when the algorithm is symmetric. Required when using `HS256` or `HS512` as the algorithm. If unspecified, the secret will be auto-generated. This field supports saving the value in Secret Manager using the [APISIX Secret](../terminology/secret.md) resource. | +| secret | string | False | | non-empty | Shared key used to sign and verify the JWT when the algorithm is symmetric. Required when using `HS256` or `HS512` as the algorithm. This field supports saving the value in Secret Manager using the [APISIX Secret](../terminology/secret.md) resource. | | public_key | string | True if `RS256` or `ES256` is set for the `algorithm` attribute. | | | RSA or ECDSA public key. This field supports saving the value in Secret Manager using the [APISIX Secret](../terminology/secret.md) resource. | | algorithm | string | False | HS256 | ["HS256","HS512","RS256","ES256"] | Encryption algorithm. | | exp | integer | False | 86400 | [1,...] | Expiry time of the token in seconds. | diff --git a/docs/zh/latest/plugins/jwt-auth.md b/docs/zh/latest/plugins/jwt-auth.md index de4ca1c122bc..23d0b77663bc 100644 --- a/docs/zh/latest/plugins/jwt-auth.md +++ b/docs/zh/latest/plugins/jwt-auth.md @@ -43,7 +43,7 @@ Consumer/Credential 端: | 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 | | ------------- | ------- | ----- | ------- | --------------------------- | ------------------------------------------------------------------------------------------------------------ | | key | string | 是 | | | 消费者的唯一密钥。 | -| secret | string | 否 | | | 当使用对称算法时,用于对 JWT 进行签名和验证的共享密钥。使用 `HS256` 或 `HS512` 作为算法时必填。如果未指定,后台将会自动生成。该字段支持使用 [APISIX Secret](../terminology/secret.md) 资源,将值保存在 Secret Manager 中。 | +| secret | string | 否 | | | 当使用对称算法时,用于对 JWT 进行签名和验证的共享密钥。使用 `HS256` 或 `HS512` 作为算法时必填。该字段支持使用 [APISIX Secret](../terminology/secret.md) 资源,将值保存在 Secret Manager 中。 | | public_key | string | 否 | | | RSA 或 ECDSA 公钥, `algorithm` 属性选择 `RS256` 或 `ES256` 算法时必选。该字段支持使用 [APISIX Secret](../terminology/secret.md) 资源,将值保存在 Secret Manager 中。 | | algorithm | string | 否 | "HS256" | ["HS256","HS512","RS256","ES256"] | 加密算法。 | | exp | integer | 否 | 86400 | [1,...] | token 的超时时间。 | diff --git a/t/plugin/jwt-auth.t b/t/plugin/jwt-auth.t index 1c28123e3b7b..0a7110330f2d 100644 --- a/t/plugin/jwt-auth.t +++ b/t/plugin/jwt-auth.t @@ -39,7 +39,7 @@ __DATA__ content_by_lua_block { local plugin = require("apisix.plugins.jwt-auth") local core = require("apisix.core") - local conf = {key = "123"} + local conf = {key = "123", secret = "my-secret-key"} local ok, err = plugin.check_schema(conf, core.schema.TYPE_CONSUMER) if not ok then @@ -50,7 +50,7 @@ __DATA__ } } --- response_body_like eval -qr/{"algorithm":"HS256","base64_secret":false,"exp":86400,"key":"123","lifetime_grace_period":0,"secret":"[a-zA-Z0-9+\\\/]+={0,2}"}/ +qr/{"algorithm":"HS256","base64_secret":false,"exp":86400,"key":"123","lifetime_grace_period":0,"secret":"my-secret-key"}/ @@ -835,7 +835,7 @@ passed content_by_lua_block { local plugin = require("apisix.plugins.jwt-auth") local core = require("apisix.core") - local conf = {key = "123", algorithm = "HS512"} + local conf = {key = "123", algorithm = "HS512", secret = "my-secret-key"} local ok, err = plugin.check_schema(conf, core.schema.TYPE_CONSUMER) if not ok then @@ -846,7 +846,7 @@ passed } } --- response_body_like eval -qr/{"algorithm":"HS512","base64_secret":false,"exp":86400,"key":"123","lifetime_grace_period":0,"secret":"[a-zA-Z0-9+\\\/]+={0,2}"}/ +qr/{"algorithm":"HS512","base64_secret":false,"exp":86400,"key":"123","lifetime_grace_period":0,"secret":"my-secret-key"}/ @@ -1222,3 +1222,49 @@ hello world --- error_code: 400 --- response_body {"error_msg":"invalid plugins configuration: failed to check the configuration of plugin jwt-auth err: failed to validate dependent schema for \"algorithm\": value should match only one schema, but matches none"} + + + +=== TEST 52: secret is required when algorithm is not RS256 or ES256 +--- config + location /t { + content_by_lua_block { + local core = require("apisix.core") + local plugin = require("apisix.plugins.jwt-auth") + -- default algorithm is HS256 + local ok, err = plugin.check_schema({ + key = "123", + }, core.schema.TYPE_CONSUMER) + assert(not ok, "secret should be required when algorithm is HS256(default)") + + ok, err = plugin.check_schema({ + key = "123", + algorithm = "HS256", + }, core.schema.TYPE_CONSUMER) + assert(not ok, "secret should be required when algorithm is HS256") + + ok, err = plugin.check_schema({ + key = "123", + algorithm = "HS512", + }, core.schema.TYPE_CONSUMER) + assert(not ok, "secret should be required when algorithm is HS512") + + ok, err = plugin.check_schema({ + key = "123", + algorithm = "RS256", + public_key = "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKebDxlvQMGyEesAL1r1nIJBkSdqu3Hr\n7noq/0ukiZqVQLSJPMOv0oxQSutvvK3hoibwGakDOza+xRITB7cs2cECAwEAAQ==\n-----END PUBLIC KEY-----" + }, core.schema.TYPE_CONSUMER) + assert(ok, "secret should not be required when algorithm is RS256") + + ok, err = plugin.check_schema({ + key = "123", + algorithm = "ES256", + public_key = "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKebDxlvQMGyEesAL1r1nIJBkSdqu3Hr\n7noq/0ukiZqVQLSJPMOv0oxQSutvvK3hoibwGakDOza+xRITB7cs2cECAwEAAQ==\n-----END PUBLIC KEY-----" + }, core.schema.TYPE_CONSUMER) + assert(ok, "secret should not be required when algorithm is ES256") + + ngx.say("passed") + } + } +--- response_body +passed diff --git a/t/plugin/public-api.t b/t/plugin/public-api.t index 6b4c9f3c7e7b..b961a3dadbd3 100644 --- a/t/plugin/public-api.t +++ b/t/plugin/public-api.t @@ -66,7 +66,8 @@ property "uri" validation failed: wrong type: expected string, got number "plugins": { "jwt-auth": { "key": "user-key", - "algorithm": "HS256" + "algorithm": "HS256", + "secret": "my-secret-key" } } }]]