Skip to content

Lemur: Fix API key expiration bugs#241

Merged
LeedrisDev merged 2 commits intomasterfrom
leedrisdev/fix-api-key-expiration
Mar 24, 2026
Merged

Lemur: Fix API key expiration bugs#241
LeedrisDev merged 2 commits intomasterfrom
leedrisdev/fix-api-key-expiration

Conversation

@LeedrisDev
Copy link
Copy Markdown

@LeedrisDev LeedrisDev commented Mar 23, 2026

Summary

API keys become unusable shortly after creation, even when set to infinite validity (TTL=-1). This PR fixes four interrelated bugs in API key timestamp handling.

Bugs Fixed

Bug 1: Timezone mismatch in expiration validation (lemur/auth/service.py)

Before:

current_time = datetime.utcnow()                            # UTC naive datetime
expired_time = datetime.fromtimestamp(access_key.issued_at)  # LOCAL naive datetime

fromtimestamp() returns local time but is compared against utcnow() (UTC). On non-UTC servers, keys expire at wrong times — off by the server's timezone offset.

After:

current_time = datetime.utcnow()                               # UTC naive datetime
expired_time = datetime.utcfromtimestamp(access_key.issued_at)  # UTC naive datetime

Bug 2: Wrong epoch stored for issued_at (lemur/api_keys/views.py, cli.py)

Before:

issued_at=int(datetime.utcnow().timestamp())

datetime.utcnow() returns UTC values, but .timestamp() interprets the naive datetime as local time, storing a wrong Unix epoch on non-UTC servers.

After:

issued_at=int(time.time())

time.time() always returns the correct UTC epoch regardless of server timezone.

Note: Bugs 1 & 2 "cancel out" on a single server with stable timezone, but break across multi-server deployments with different timezones or during DST transitions.

Bug 3: CLI doesn't convert TTL to int (lemur/api_keys/cli.py)

Before:

ttl=ttl,  # string from CLI arg, e.g. "-1"

CLI arguments are strings. "-1" != -1 (string vs int), so create_token won't remove the exp claim from the JWT, causing the token to get the default 1-day expiration even for "infinite" keys created via CLI.

After:

ttl=int(ttl),

Bug 4: No TTL validation (lemur/api_keys/schemas.py)

TTL=0 would silently create an immediately-expired key. Added @validates("ttl") to all API key input schemas to reject TTL=0 and TTL < -1. Only TTL=-1 (infinite) and positive integers (days) are accepted.

Hardening: Disable PyJWT built-in exp verification (lemur/auth/service.py)

Added "verify_exp": False to jwt.decode() options since expiration is already handled manually in login_required. This prevents future PyJWT behavior changes from breaking infinite API keys (which have no exp claim in their JWT). Manual exp checking is added for regular user tokens.

Test plan

  • Existing API key tests pass
  • New TTL validation tests: TTL=0 → 400, TTL=-2 → 400, TTL=-1 → 200, TTL=30 → 200

…idation

Fix multiple bugs causing API keys to expire incorrectly or become
unusable, even when set to infinite validity (TTL=-1).
@LeedrisDev LeedrisDev requested review from a team as code owners March 23, 2026 19:38
@LeedrisDev LeedrisDev changed the title Fix API key expiration bugs Lemur: Fix API key expiration bugs Mar 23, 2026
evan-datadog
evan-datadog previously approved these changes Mar 23, 2026
Copy link
Copy Markdown

@evan-datadog evan-datadog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind also fixing line 84 so it no longer uses utcnow in setup.py ?

Use datetime.now(timezone.utc) which produces a timezone-aware
datetime with correct ISO format (includes +00:00 suffix).
@LeedrisDev
Copy link
Copy Markdown
Author

Mind also fixing line 84 so it no longer uses utcnow in setup.py ?

Done 👍

@LeedrisDev LeedrisDev merged commit 80645f8 into master Mar 24, 2026
9 checks passed
@LeedrisDev LeedrisDev deleted the leedrisdev/fix-api-key-expiration branch March 24, 2026 11:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants