-
Notifications
You must be signed in to change notification settings - Fork 47
Description
Hi,
First of all, thank you for creating + maintaining this package.
I'm on drf-oidc-auth version 1.0.0 and Authlib 0.15.3.
I was looking into the code for handling the 'exp' and 'iat' headers, and I have the feeling there's some inconsistency in how the leeway parameter is used/interpreted. Let's introduce two names:
relative leeway: a time delta. Accept the header if the difference between current time and stated time is no more than this time delta.
absolute leeway: a boundary value obtained from subtracting the relative leeway from the current time.
In class JSONWebTokenAuthentication, method validate_claims in oidc_auth/authentication.py, the function id_token.validate is called with an absolute leeway:
id_token.validate(
now=int(time.time()),
leeway=int(time.time()-api_settings.OIDC_LEEWAY)
)
The DRFIDToken defined in oidc_auth/authentication.py indeed seems to assume an absolute leeway (self['iat'] < leeway):
class DRFIDToken(IDToken):
def validate_exp(self, now, leeway):
super(DRFIDToken, self).validate_exp(now, leeway)
if now > self['exp']:
msg = _('Invalid Authorization header. JWT has expired.')
raise AuthenticationFailed(msg)
def validate_iat(self, now, leeway):
super(DRFIDToken, self).validate_iat(now, leeway)
if self['iat'] < leeway:
msg = _('Invalid Authorization header. JWT too old.')
raise AuthenticationFailed(msg)
However, the validation of exp in package authlib , file rfc7519/claims.py (which is what the super call leads to) looks as follows:
def validate_exp(self, now, leeway):
"""The "exp" (expiration time) claim identifies the expiration time on
or after which the JWT MUST NOT be accepted for processing. The
processing of the "exp" claim requires that the current date/time
MUST be before the expiration date/time listed in the "exp" claim.
Implementers MAY provide for some small leeway, usually no more than
a few minutes, to account for clock skew. Its value MUST be a number
containing a NumericDate value. Use of this claim is OPTIONAL.
"""
if 'exp' in self:
exp = self['exp']
if not _validate_numeric_time(exp):
raise InvalidClaimError('exp')
if exp < (now - leeway):
raise ExpiredTokenError()
The line exp < (now - leeway) is a check for a relative leeway.
I notice that there has been a recent change from jwkest to authlib, so I guess this may be related. However, I haven't been able to find exact proof that this is where this inconsistency originates.
Could you confirm if my analysis is correct and/or sounds plausible? And if so, what your ideal solution would look like? I could imagine that the checks in this package's code would also have to change to relative leeways. If so, I might be able to supply a pull request fixing this.
Thanks,
Florian