Skip to content

feat: Include issued_at and expires_at in token response, respect server timestamps on client#892

Open
liudonggalaxy wants to merge 1 commit into
authlib:mainfrom
liudonggalaxy:Dongliu/include_expires_at_in_token_response
Open

feat: Include issued_at and expires_at in token response, respect server timestamps on client#892
liudonggalaxy wants to merge 1 commit into
authlib:mainfrom
liudonggalaxy:Dongliu/include_expires_at_in_token_response

Conversation

@liudonggalaxy

@liudonggalaxy liudonggalaxy commented May 15, 2026

Copy link
Copy Markdown
Contributor

What kind of change does this PR introduce?

This is a feature implementation

Add issued_at and expires_at to the bearer token response body, and teach the client-side OAuth2Token to prefer the server-provided issued_at over the local clock when computing expiration.

Server side (BearerTokenGenerator.generate())

  • Captures a single time.time() call and resolves expires_in before calling access_token_generator(), storing both as self._issued_at and self._expires_in
  • issued_at and expires_at are included in the response whenever expires_in is present
  • For JWT tokens, JWTBearerTokenGenerator.access_token_generator() reads self._issued_at and self._expires_in directly, guaranteeing iat == issued_at and exp == expires_at — no duplicate time.time() or _get_expires_in() calls

Client side (OAuth2Token)

  • When the server provides issued_at, the client computes expires_at from it instead of from the local clock, avoiding clock-skew issues
  • Invalid issued_at values (zero, negative, non-numeric) fall back to the client clock gracefully
  • Falls back to time.time() when issued_at is absent (backward compatible)

Persistence (save_token helpers)

  • The default save_token helpers in both the SQLAlchemy and Django integrations now filter the token dict to known model columns before persisting, so new response-only fields do not break existing schemas

Checklist

  • The commits follow the conventional commits specification.
  • You ran the linters with prek.
  • You wrote unit test to demonstrate the bug you are fixing, or to stress the feature you are bringing.
  • You reached 100% of code coverage on the code you edited, without abusive use of pragma: no cover
  • If this PR is about a new feature, or a behavior change, you have updated the documentation accordingly.

  • You consent that the copyright of your pull request source code belongs to Authlib's author.

@liudonggalaxy liudonggalaxy force-pushed the Dongliu/include_expires_at_in_token_response branch from c030605 to c6d19d0 Compare May 15, 2026 14:40
@liudonggalaxy liudonggalaxy changed the title Include expires_at in bearer token response Include expires_at in JWT access token response May 15, 2026
@liudonggalaxy liudonggalaxy force-pushed the Dongliu/include_expires_at_in_token_response branch from c6d19d0 to 61bbaba Compare May 15, 2026 15:36
@liudonggalaxy liudonggalaxy changed the title Include expires_at in JWT access token response Include issued_at and expires_at in token response May 15, 2026
@liudonggalaxy liudonggalaxy force-pushed the Dongliu/include_expires_at_in_token_response branch from 61bbaba to b51ee45 Compare May 15, 2026 15:49
@liudonggalaxy liudonggalaxy changed the title Include issued_at and expires_at in token response Include issued_at and expires_at in token response, respect server timestamps on client May 15, 2026
@liudonggalaxy liudonggalaxy force-pushed the Dongliu/include_expires_at_in_token_response branch 2 times, most recently from 9234dc8 to 65cc5c6 Compare May 15, 2026 16:13
Add issued_at and expires_at to the bearer token response. Both values
derive from a single time.time() call and a single expires_in resolution
in generate(), before access_token_generator() is called.  This guarantees
that the response fields and the JWT iat/exp claims are always identical.

On the client side, OAuth2Token prefers the server-provided issued_at when
computing expires_at, avoiding clock-skew between client and server.
Invalid issued_at values (zero, negative, non-numeric) fall back to the
client clock gracefully.

Also hardens the default save_token helpers in the SQLAlchemy and Django
integrations to filter the token dict to known model columns before
persisting.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@liudonggalaxy liudonggalaxy force-pushed the Dongliu/include_expires_at_in_token_response branch from 65cc5c6 to fa97da4 Compare May 15, 2026 16:44
Comment thread .gitignore
uv.lock
.env
coverage.xml
authlib.iml

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ignore IntelliJ IDE project file

@liudonggalaxy liudonggalaxy marked this pull request as ready for review May 15, 2026 16:59
@liudonggalaxy liudonggalaxy changed the title Include issued_at and expires_at in token response, respect server timestamps on client feat: Include issued_at and expires_at in token response, respect server timestamps on client May 15, 2026
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.

1 participant