Summary
When using jwt.encode function, known time claims such as exp, iat and nbf lose microseconds precision if their value is a datetime.
This happens because the underlying structure used by utctimetuple and timegm functions does not store time units below full seconds (see tm struct at https://pubs.opengroup.org/onlinepubs/9799919799/).
Culprit is line at
|
for time_claim in ["exp", "iat", "nbf"]: |
|
# Convert datetime to a intDate value in known time-format claims |
|
if isinstance(payload.get(time_claim), datetime): |
|
payload[time_claim] = timegm(payload[time_claim].utctimetuple()) |
Example
Code
import datetime as dt
import jwt
dt_iat = dt.datetime(2025, 1, 1, 0, 0, 0, 123456, dt.UTC)
result = jwt.decode(jwt.encode({'iat': dt_iat}, 'secret'), 'secret', algorithms = ['HS256'])
decoded_dt_iat = dt.datetime.fromtimestamp(result['iat'], tz=dt.UTC)
print(f'Original: {dt_iat}')
print(f'Decoded: {decoded_dt_iat}')
print(f'Original timestamp: {dt_iat.timestamp()}')
print(f'Decoded timestamp: {decoded_dt_iat.timestamp()}')
returns
Original: 2025-01-01 00:00:00.123456+00:00
Decoded: 2025-01-01 00:00:00+00:00
Original timestamp: 1735689600.123456
Decoded timestamp: 1735689600.0
currently at master (dd44834).
It should return
Original: 2025-01-01 00:00:00.123456+00:00
Decoded: 2025-01-01 00:00:00.123456+00:00
Original timestamp: 1735689600.123456
Decoded timestamp: 1735689600.123456
System Information
{
"cryptography": {
"version": "46.0.3"
},
"implementation": {
"name": "CPython",
"version": "3.13.11"
},
"platform": {
"release": "6.12.63-1-lts",
"system": "Linux"
},
"pyjwt": {
"version": "2.10.1"
}
}
I will submit a PR shortly to tackle this.
Summary
When using
jwt.encodefunction, known time claims such asexp,iatandnbflose microseconds precision if their value is a datetime.This happens because the underlying structure used by
utctimetupleandtimegmfunctions does not store time units below full seconds (seetmstruct at https://pubs.opengroup.org/onlinepubs/9799919799/).Culprit is line at
pyjwt/jwt/api_jwt.py
Lines 127 to 130 in dd44834
Example
Code
returns
currently at master (dd44834).
It should return
System Information
I will submit a PR shortly to tackle this.