python-jose icon indicating copy to clipboard operation
python-jose copied to clipboard

Token doesn't expire immediately

Open jbmoorhouse opened this issue 4 years ago • 6 comments
trafficstars

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?

jbmoorhouse avatar Apr 16 '21 14:04 jbmoorhouse

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

FalseDev avatar May 22 '21 15:05 FalseDev

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 avatar Aug 29 '21 08:08 bkuczenski

@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.

AnthonyA1223 avatar Nov 04 '22 10:11 AnthonyA1223

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 avatar Apr 14 '23 06:04 umang-gramener

@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.

mpdavis avatar Apr 14 '23 19:04 mpdavis

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

corentinclichy avatar Aug 12 '23 17:08 corentinclichy

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.

fraboniface avatar Sep 14 '23 09:09 fraboniface