Skip to content

Token Expiration Timezone Bug On Non-UTC System Clocks #1594

@JonnyWaffles

Description

@JonnyWaffles

Describe the bug
Hi friends, this is related to #1291. The problem is mixing timezone-naive and timezone-aware datetime operations in the _get_token_from_authentication_server method in the oauth2_validators module. Below are the steps

Step 1: Naive Timestamp Creation (Lines 407-409)

max_caching_time = datetime.now() + timedelta(
seconds=oauth2_settings.RESOURCE_SERVER_TOKEN_CACHING_SECONDS
)

  • datetime.now() creates a timezone-naive timestamp using the system's local time
  • On my Eastern Time machine, this would be something like 2025-09-02 16:06:00 (4:06 PM ET)
  • This timestamp has no timezone information attached to it

Step 2: Expires Assignment (Lines 409-414)

if "exp" in content:
expires = datetime.utcfromtimestamp(content["exp"])
if expires > max_caching_time:
expires = max_caching_time
else:
expires = max_caching_time

  • When there's no "exp" in the token content, expires gets set to the naive max_caching_time
  • Since the default RESOURCE_SERVER_TOKEN_CACHING_SECONDS is 300 seconds (5 minutes), this code path is frequently taken
  • Note any well-behaved OAuth provider will provide exp as UTC

Step 3: Timezone Conversion (Lines 418-421)

if settings.USE_TZ:
expires = make_aware(
expires, timezone=get_timezone(oauth2_settings.AUTHENTICATION_SERVER_EXP_TIME_ZONE)
)

  • make_aware() treats the naive timestamp as if it were in the specified timezone
  • oauth2_settings.AUTHENTICATION_SERVER_EXP_TIME_ZONE defaults to UTC
  • My Eastern Time timestamp (4:06 PM ET) gets interpreted as 4:06 PM UTC
  • This effectively makes the token expire 4-5 hours earlier than intended (depending on EST/EDT)

As I understand it, the naive datetime creation is the primary cause. We should either use UTC, datetime.utcnow() for the max_caching_time or Django's timezone.now().

I may be missing something, so please correct me if I am!

To Reproduce
Validate an external OAuth Provider token on a non-UTC host. In my example I am running the resource provider on a Windows machine whose system clock is in Eastern Time (-4 thanks to day light savings).

Expected behavior
When a token expires in the feature, and the max caching time is 5 minutes, the token should be valid.

Version
3.0.1

  • I have tested with the latest published release and it's still a problem.
  • I have tested with the master branch and it's still a problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions