Skip to content

jwt.encode loses microseconds precision when using datetime for known time claims #1126

@rodrigovillarbello

Description

@rodrigovillarbello

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

pyjwt/jwt/api_jwt.py

Lines 127 to 130 in dd44834

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

$ python -m jwt.help
{
  "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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions