pyjwt: The token is not yet valid (iat).
We found an issue in one of our tests in the recent update of yours. Our package works with pyjwt==2.5.0
but it breaks with pyjwt==2.6.0
. We will give more details on the issue once we explore it more and will try to provide a minimal example that reproduces the error. However, may I ask you to check if the latests changes could have broken backawards compatibility? We are particularly suspicious of #794. We think this because the error message we get: The token is not yet valid (iat)
.
We are sorry we could not provide more details yet.
System Information
$ python -m jwt.help
{
"cryptography": {
"version": "38.0.1"
},
"implementation": {
"name": "CPython",
"version": "3.10.6"
},
"platform": {
"release": "5.19.16-76051916-generic",
"system": "Linux"
},
"pyjwt": {
"version": "2.6.0"
}
}
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 4
- Comments: 21 (6 by maintainers)
Commits related to this issue
- fix: use datetime.datetime.timestamp function to have a milliseconds Fixes #814 — committed to daillouf/pyjwt by daillouf 2 years ago
- fix: use datetime.datetime.timestamp function to have a milliseconds (#821) Fixes #814 — committed to jpadilla/pyjwt by daillouf 2 years ago
- Disable verifying token issued-at timestamp PyJWT v2.8.0 verifies `iat` (issued-at timestamp) by default. There are several discussions on disabling this check, since it is not within spec. [Cognito'... — committed to DavidLiuGit/pycognito by DavidLiuGit 3 months ago
I’ve also encountered this issue, particularly in tests where the token is issued within a few milliseconds of when it gets used. The problem is that the
iat
is assumed to be an integer, while the RFC allows floats. If a token is issued with a floatiat
and decoded within that second, the code will test against the integer second, which is less than the floatiat
. This results inImmatureSignatureError
being raised.Here is an example that used to succeed, but now raises an error:
I suggest either allowing full float calculations or casting the input
iat
to an int.Y’all this was litigated previously at https://github.com/jpadilla/pyjwt/issues/190. The JWT spec does NOT say to reject tokens with
iat
(“issued at”) in the future, so this behavior goes beyond the spec and is inconsistent with many other JWT libraries.If token issuers want clients to specify that a token should not be accepted before a certain timestamp (which puts additional constraints upon clients by implying that clients’ clocks should keep relatively in sync with a central clock source and/or need to check it with leeway) then the issuer is supposed to set
nbf
(“not before”):I am currently getting bit by this issue a lot in a large enterprise microservices environment (where token issuer, token user, and token-accepting server which validates offline using RSA are three different machines) where clock drift is coming into play. Myself and 10+ other people have now wasted multiple days of person-time trying to figure out why tokens were being rejected, talking about how best to address it, and managing the workloads & deliverables of the people investigating & talking about this.
Could this issue be re-opened and could the proper fix be to set the default value of
verify_iat
toFalse
and publish a 3.0 since that’s a breaking change?Clients who understand the risks and want to engage in this extra-spec behavior should opt in by setting
verify_iat
toTrue
, and the need to do this should be announced in the changelog for this new major version. (Or maybe there could be a global variable inpyjwt
to control theverify_iat
default?)Hi. Had the same issue, when updating from 2.4.0 to 2.6.0… drove me crazy this bug.
Solved it by simply deactivate the check with: options={“verify_iat”:False} in decode:
self.decoded_token = jwt.decode( token_str, ActivationToken.pub_key, algorithms=["RS256"], options={"verify_iat":False} )
But I have to admit, I have wrote a custom check for the iat already before that update with an higher tolerance value (I think this is what you have labeled as leeway).It’s yes and no, since most JWT libraries in other languages also support the
int
type this could cause an issue. I agree with the fact that float has a bit more precision than int but to tackle this synchronization issue the recommended way isleeway time
. So adding the minimum leeway time will help them without changing the custom logic they have now.An example could be,
jwt.decode(jwt.encode({'iat': int(time.time())+leeway}, 'secret', algorithm='HS256'), 'secret', algorithms=['HS256'])
With this,
PyJWT
will be in sync with other frameworks/libraries in other languages as well.Lately, I’ve been encountering this error
The token is not yet valid (iat)
(as of March 2024). Interestingly, the solution was simply to resynchronize my computer clock onWindows 11 23H2 (OS build 22631.3296)
working on WSL2. Has anyone else encountered this issue where the clock gets out of sync, as I have experienced it multiple times this week! My computer is relatively new, so I doubt the MB battery is causing the problem.Just for fairness, I did some due diligence on the other libraries. Every other library I’ve found that does this has its own respective issue complaining about it. 😉
Libraries I found that do not check that
iat
is >= now:Libraries that do (and their respective bug complaints):
Maybe this needs to be clarified in the spec since there’s a pretty divided polity…
what if instead of: https://github.com/jpadilla/pyjwt/blob/0cfc0978a6c9dc01d89043d203b7f397e78822c2/jwt/api_jwt.py#L190
we just did
Wouldn’t that mostly address the issues seen? Anything else would be addressed by specifying a leeway when decoding. unsure if i’m missing anything else.
Different servers could have different time settings, especially when they are not connected to the internet, like a private network. Not every private network has a clock synchronization mechanism.
I’m going to be submitting an errata request for RFC 7519 about this. I’ll be making my draft of that & centralizing the Github-side discussion here:
Discussion: JWT tokens containing
iat
values in the future should not be rejected@jpadilla your solution should work,
I also got a few tests failing when upgrading pyjwt :
the value of «now» seems not to include milliseconds, because
per timegm source code, it’s only seconds :
we could bypass this with a leeway of 1 second, but that’s a lot of leeway