diff --git a/util/security/jwtutil.py b/util/security/jwtutil.py index dc190838f..7e2bc6cee 100644 --- a/util/security/jwtutil.py +++ b/util/security/jwtutil.py @@ -1,5 +1,6 @@ import re +from calendar import timegm from datetime import datetime, timedelta from jwt import PyJWT from jwt.exceptions import ( @@ -42,6 +43,9 @@ class StrictJWT(PyJWT): # Do all of the other checks super(StrictJWT, self)._validate_claims(payload, options, audience, issuer, leeway, **kwargs) + now = timegm(datetime.utcnow().utctimetuple()) + self._reject_future_iat(payload, now, leeway) + if 'exp' in payload and options.get('exp_max_s') is not None: # Validate that the expiration was not more than exp_max_s seconds after the issue time # or in the absense of an issue time, more than exp_max_s in the future from now @@ -58,6 +62,16 @@ class StrictJWT(PyJWT): raise InvalidTokenError('Token was signed for more than %s seconds from %s', max_signed_s, start_time) + def _reject_future_iat(self, payload, now, leeway): + try: + iat = int(payload['iat']) + except ValueError: + raise DecodeError('Issued At claim (iat) must be an integer.') + + if iat > (now + leeway): + raise InvalidIssuedAtError('Issued At claim (iat) cannot be in' + ' the future.') + def exp_max_s_option(max_exp_s): return {