1515-- limitations under the License.
1616--
1717local core = require (" apisix.core" )
18- local jwt = require (" resty.jwt" )
1918local consumer_mod = require (" apisix.consumer" )
2019local new_tab = require (" table.new" )
2120local auth_utils = require (" apisix.utils.auth" )
@@ -27,8 +26,9 @@ local table_insert = table.insert
2726local table_concat = table.concat
2827local ngx_re_gmatch = ngx .re .gmatch
2928local plugin_name = " jwt-auth"
30- local schema_def = require (" apisix.schema_def" )
3129
30+ local schema_def = require (" apisix.schema_def" )
31+ local jwt_parser = require (" apisix.plugins.jwt-auth.parser" )
3232
3333local schema = {
3434 type = " object" ,
@@ -60,6 +60,14 @@ local schema = {
6060 },
6161 realm = schema_def .get_realm_schema (" jwt" ),
6262 anonymous_consumer = schema_def .anonymous_consumer_schema ,
63+ claims_to_verify = {
64+ type = " array" ,
65+ items = {
66+ type = " string" ,
67+ enum = {" exp" ," nbf" },
68+ },
69+ uniqueItems = true ,
70+ },
6371 },
6472}
6573
@@ -77,7 +85,21 @@ local consumer_schema = {
7785 },
7886 algorithm = {
7987 type = " string" ,
80- enum = {" HS256" , " HS512" , " RS256" , " ES256" },
88+ enum = {
89+ " HS256" ,
90+ " HS384" ,
91+ " HS512" ,
92+ " RS256" ,
93+ " RS384" ,
94+ " RS512" ,
95+ " ES256" ,
96+ " ES384" ,
97+ " ES512" ,
98+ " PS256" ,
99+ " PS384" ,
100+ " PS512" ,
101+ " EdDSA" ,
102+ },
81103 default = " HS256"
82104 },
83105 exp = {type = " integer" , minimum = 1 , default = 86400 },
@@ -97,16 +119,30 @@ local consumer_schema = {
97119 {
98120 properties = {
99121 algorithm = {
100- enum = {" HS256" , " HS512" },
122+ enum = {" HS256" , " HS384 " , " HS512" },
101123 default = " HS256"
102124 },
103125 },
104126 },
105127 {
106128 properties = {
107- public_key = {type = " string" },
129+ public_key = {
130+ type = " string" ,
131+ minLength = 1 ,
132+ },
108133 algorithm = {
109- enum = {" RS256" , " ES256" },
134+ enum = {
135+ " RS256" ,
136+ " RS384" ,
137+ " RS512" ,
138+ " ES256" ,
139+ " ES384" ,
140+ " ES512" ,
141+ " PS256" ,
142+ " PS384" ,
143+ " PS512" ,
144+ " EdDSA" ,
145+ },
110146 },
111147 },
112148 required = {" public_key" },
@@ -141,15 +177,21 @@ function _M.check_schema(conf, schema_type)
141177 return false , err
142178 end
143179
144- if (conf .algorithm == " HS256" or conf .algorithm == " HS512" ) and not conf .secret then
145- return false , " property \" secret\" is required " ..
146- " when \" algorithm\" is \" HS256\" or \" HS512\" "
147- elseif conf .base64_secret then
180+ local is_hs_alg = conf .algorithm :sub (1 , 2 ) == " HS"
181+ if is_hs_alg and not conf .secret then
182+ return false , " property \" secret\" is required when using HS based algorithms"
183+ end
184+
185+ if conf .base64_secret then
148186 if ngx_decode_base64 (conf .secret ) == nil then
149187 return false , " base64_secret required but the secret is not in base64 format"
150188 end
151189 end
152190
191+ if not is_hs_alg and not conf .public_key then
192+ return false , " missing valid public key"
193+ end
194+
153195 return true
154196end
155197
@@ -232,15 +274,16 @@ local function get_secret(conf)
232274 return secret
233275end
234276
235- local function get_auth_secret ( auth_conf )
236- if not auth_conf . algorithm or auth_conf . algorithm == " HS256 "
237- or auth_conf .algorithm == " HS512 " then
238- return get_secret (auth_conf )
239- elseif auth_conf . algorithm == " RS256 " or auth_conf . algorithm == " ES256 " then
240- return auth_conf .public_key
277+
278+ local function get_auth_secret ( consumer )
279+ if not consumer . auth_conf . algorithm or consumer . auth_conf .algorithm : sub ( 1 , 2 ) == " HS " then
280+ return get_secret (consumer . auth_conf )
281+ else
282+ return consumer . auth_conf .public_key
241283 end
242284end
243285
286+
244287local function find_consumer (conf , ctx )
245288 -- fetch token and hide credentials if necessary
246289 local jwt_token , err = fetch_jwt_token (conf , ctx )
@@ -249,19 +292,19 @@ local function find_consumer(conf, ctx)
249292 return nil , nil , " Missing JWT token in request"
250293 end
251294
252- local jwt_obj = jwt :load_jwt (jwt_token )
253- core .log .info (" jwt object: " , core .json .delay_encode (jwt_obj ))
254- if not jwt_obj .valid then
255- err = " JWT token invalid: " .. jwt_obj .reason
295+ local jwt , err = jwt_parser .new (jwt_token )
296+ if not jwt then
297+ err = " JWT token invalid: " .. err
256298 if auth_utils .is_running_under_multi_auth (ctx ) then
257299 return nil , nil , err
258300 end
259301 core .log .warn (err )
260302 return nil , nil , " JWT token invalid"
261303 end
304+ core .log .debug (" parsed jwt object: " , core .json .delay_encode (jwt , true ))
262305
263306 local key_claim_name = conf .key_claim_name
264- local user_key = jwt_obj .payload and jwt_obj .payload [key_claim_name ]
307+ local user_key = jwt .payload and jwt .payload [key_claim_name ]
265308 if not user_key then
266309 return nil , nil , " missing user key in JWT token"
267310 end
@@ -272,7 +315,7 @@ local function find_consumer(conf, ctx)
272315 return nil , nil , " Invalid user key in JWT token"
273316 end
274317
275- local auth_secret , err = get_auth_secret (consumer . auth_conf )
318+ local auth_secret , err = get_auth_secret (consumer )
276319 if not auth_secret then
277320 err = " failed to retrieve secrets, err: " .. err
278321 if auth_utils .is_running_under_multi_auth (ctx ) then
@@ -281,23 +324,32 @@ local function find_consumer(conf, ctx)
281324 core .log .error (err )
282325 return nil , nil , " failed to verify jwt"
283326 end
284- local claim_specs = jwt :get_default_validation_options (jwt_obj )
285- claim_specs .lifetime_grace_period = consumer .auth_conf .lifetime_grace_period
286-
287- jwt_obj = jwt :verify_jwt_obj (auth_secret , jwt_obj , claim_specs )
288- core .log .info (" jwt object: " , core .json .delay_encode (jwt_obj ))
289327
290- if not jwt_obj .verified then
291- err = " failed to verify jwt: " .. jwt_obj .reason
328+ -- Now verify the JWT signature
329+ if not jwt :verify_signature (auth_secret ) then
330+ local err = " failed to verify jwt: signature mismatch: " .. jwt .signature
292331 if auth_utils .is_running_under_multi_auth (ctx ) then
293332 return nil , nil , err
294333 end
295334 core .log .warn (err )
296335 return nil , nil , " failed to verify jwt"
297336 end
298337
338+ -- Verify the JWT registered claims
339+ local ok , err = jwt :verify_claims (conf .claims_to_verify , {
340+ lifetime_grace_period = consumer .auth_conf .lifetime_grace_period
341+ })
342+ if not ok then
343+ err = " failed to verify jwt: " .. err
344+ if auth_utils .is_running_under_multi_auth (ctx ) then
345+ return nil , nil , err
346+ end
347+ core .log .error (err )
348+ return nil , nil , " failed to verify jwt"
349+ end
350+
299351 if conf .store_in_ctx then
300- ctx .jwt_auth_payload = jwt_obj .payload
352+ ctx .jwt_auth_payload = jwt .payload
301353 end
302354
303355 return consumer , consumer_conf
0 commit comments