@@ -172,7 +172,7 @@ func New(_ context.Context, next http.Handler, config *Config, name string) (htt
172
172
plugin := JWTPlugin {
173
173
next : next ,
174
174
name : name ,
175
- parser : jwt .NewParser (jwt .WithValidMethods (config .ValidMethods )),
175
+ parser : jwt .NewParser (jwt .WithValidMethods (config .ValidMethods ), jwt . WithJSONNumber () ),
176
176
secret : key ,
177
177
issuers : canonicalizeDomains (config .Issuers ),
178
178
clients : createClients (config .InsecureSkipVerify ),
@@ -327,8 +327,7 @@ func (plugin *JWTPlugin) validate(request *http.Request, variables *TemplateVari
327
327
if ! plugin .validateClaim (claim , claims , requirements , variables ) {
328
328
err := fmt .Errorf ("claim is not valid: %s" , claim )
329
329
// If the token is older than our freshness window, we allow that reauthorization might fix it
330
- iat , ok := claims ["iat" ]
331
- if ok && plugin .freshness != 0 && time .Now ().Unix ()- int64 (iat .(float64 )) > plugin .freshness {
330
+ if plugin .allowRefresh (claims ) {
332
331
return http .StatusUnauthorized , err
333
332
} else {
334
333
return http .StatusForbidden , err
@@ -342,6 +341,20 @@ func (plugin *JWTPlugin) validate(request *http.Request, variables *TemplateVari
342
341
return http .StatusOK , nil
343
342
}
344
343
344
+ // allowRefresh returns true if freshness window is configured and the token has an iat claim that is older than the freshness window.
345
+ func (plugin * JWTPlugin ) allowRefresh (claims jwt.MapClaims ) bool {
346
+ if plugin .freshness == 0 {
347
+ return false
348
+ }
349
+ iat , ok := claims ["iat" ]
350
+ if ! ok {
351
+ return false
352
+ }
353
+
354
+ value , err := iat .(json.Number ).Int64 ()
355
+ return err == nil && time .Now ().Unix ()- value > plugin .freshness
356
+ }
357
+
345
358
// mapClaimsToHeaders maps any claims to headers as specified in the headerMap configuration.
346
359
func (plugin * JWTPlugin ) mapClaimsToHeaders (claims jwt.MapClaims , request * http.Request ) {
347
360
for header , claim := range plugin .headerMap {
@@ -387,6 +400,19 @@ func (requirement ValueRequirement) Validate(value any, variables *TemplateVaria
387
400
return false
388
401
}
389
402
return fnmatch .Match (value , required , 0 ) || value == fmt .Sprintf ("*.%s" , required )
403
+
404
+ case json.Number :
405
+ switch requirement .value .(type ) {
406
+ case int :
407
+ converted , err := value .Int64 ()
408
+ return err == nil && converted == int64 (requirement .value .(int ))
409
+ case float64 :
410
+ converted , err := value .Float64 ()
411
+ return err == nil && converted == requirement .value .(float64 )
412
+ default :
413
+ log .Printf ("unsupported requirement type for json.Number comparison: %T %v" , requirement .value , requirement .value )
414
+ return false
415
+ }
390
416
}
391
417
392
418
return reflect .DeepEqual (value , requirement .value )
0 commit comments