python-jose
python-jose copied to clipboard
Token doesn't expire immediately
Jose version
3.2.0
Problem/Question
Token expiration. I was expecting the following token to raise an expiration error.
from datetime import datetime
from jose import jwt
token = jwt.encode(
claims={"sub": "1", "exp": datetime.utcnow()},
key="secret"
)
jwt.decode(token, "secret") # Token hasn't expired
{'sub': '1', 'exp': <now>}
Even after applying a time delay (for me 0.3s consistently works), the token doesn't appear to have expired.
from datetime import datetime
from jose import jwt
import time
token = jwt.encode(
claims={"sub": "1", "exp": datetime.utcnow()},
key="secret"
)
time.sleep(0.3)
jwt.decode(token, "secret") # Token hasn't expired
{'sub': '1', 'exp': <now>}
Additional notes
From the source code, it looks like the issue may be here?
>>> print(timegm(datetime.utcnow().utctimetuple()))
... 1618582273
>>> time.sleep(0.3)
>>> print(timegm(datetime.utcnow().utctimetuple()))
... 1618582273
Was curious if this behaviour is expected?
The logic to check if the token has expired must be done by ourselves, there's no RFC guiding the inclusion of expiry info in a JWT token, so it cannot be implemented into the library itself.
Besides JWT is also used in cases where the token has no expiry
It's a bug. The RFC specifies that "The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing." RFC 7519 section 4.1.4 (emphasis added).
This suggests that the test in the code here should be <= instead of <
@bkuczenski the timegm function returns a unix timestamp with a resolution of a second, therefor it will expire anything older than a second from the moment you set your token expiration.
You can test this out by trying
timegm(datetime.utcnow().utctimetuple())
and
timegm((datetime.utcnow()+timedelta(seconds=1)).utctimetuple())
and seeing that the difference between the two is actually 1.
I know its an old issue, But even in Apr 2023, This exp claim validation is not happening. Even if we keep say datetime.now() + timedelta(seconds=5), It is validating the token always. Even after say 10minutes
@umang-gramener A token not expiring immediately is a different issue than a token not expiring after 10 minutes. I would check that you haven't inadvertently bypasses expiration checking and that the token you are trying to validate actually has an exp claim.
If that doesn't clear up the issue, I would open a new issue with an example token that doesn't validate expiration.
I have the issue on my side too. Any updates on this ?
I set exp with datetime.now() + timedelta(minutes=refresh_time_exp) But even if I put 10 sec I still get the token validated by the jwt.decode function
To those who still see a very large delay @corentinclichy @umang-gramener, check for timezone consistency. I tracked down the maximum delay with no exception raised and it turned out to be my time difference with UTC. I changed datetime.now() to datetime.utcnow() in my code and it fixed the issue.