[PR #8134] [MERGED] fix(oauth-provider)!: Keep auth_time across id_token refresh #16014

Closed
opened 2026-04-13 10:21:03 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/8134
Author: @grant0417
Created: 2/24/2026
Status: Merged
Merged: 2/28/2026
Merged by: @Bekacru

Base: canaryHead: fix/refresh-auth-time


📝 Commits (5)

  • 0b2c713 fix(oauth-provider)!: Keep auth_time across id_token refresh
  • a1d78e3 Merge branch 'canary' into fix/refresh-auth-time
  • c35207e update docs
  • d4d8ad7 convert to date
  • 094ee97 fmt

📊 Changes

6 files changed (+93 additions, -6 deletions)

View changed files

📝 docs/content/docs/plugins/oauth-provider.mdx (+6 -0)
📝 packages/oauth-provider/src/authorize.ts (+4 -0)
📝 packages/oauth-provider/src/schema.ts (+4 -0)
📝 packages/oauth-provider/src/token.test.ts (+43 -0)
📝 packages/oauth-provider/src/token.ts (+30 -6)
📝 packages/oauth-provider/src/types/index.ts (+6 -0)

📄 Description

  • Fix auth_time claim in ID tokens to remain stable across refresh token grants, per https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse
  • Previously, auth_time was derived from ctx.context.session at token creation time, which falls back to "now" during refresh (no session in context), causing auth_time to drift on each refresh
  • Now auth_time is captured from the session during authorization, stored in the verification value, persisted on the refresh token record, and carried forward through rotation

Breaking changes

  • Adds a new nullable authTime column to the oauthRefreshToken table (requires migration)
  • Existing refresh tokens will have authTime = NULL, in which case auth_time is omitted from the ID token

Summary by cubic

Keeps auth_time in ID tokens stable across refresh, per OIDC Core 1.0 §12.2. Captures the original login time and carries it through token rotation so refreshed ID tokens keep the same auth_time.

  • Bug Fixes

    • Capture session.createdAt at authorization and include in the verification value.
    • Persist authTime on refresh tokens as a Date; read it on refresh and pass it to ID token creation.
    • Convert to seconds for the auth_time claim; omit when authTime is missing.
    • Added tests to confirm auth_time remains unchanged after refresh.
    • Documented the new authTime field in the oauthRefreshToken table.
  • Migration

    • Add a new nullable authTime (Date) column to oauthRefreshToken.
    • Existing refresh tokens will have authTime = NULL; refreshed ID tokens will omit auth_time until the user signs in again.

Written for commit 094ee972cd. Summary will update on new commits.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/8134 **Author:** [@grant0417](https://github.com/grant0417) **Created:** 2/24/2026 **Status:** ✅ Merged **Merged:** 2/28/2026 **Merged by:** [@Bekacru](https://github.com/Bekacru) **Base:** `canary` ← **Head:** `fix/refresh-auth-time` --- ### 📝 Commits (5) - [`0b2c713`](https://github.com/better-auth/better-auth/commit/0b2c7137bbf0ee3fdfbfa326b76fb64e555297f2) fix(oauth-provider)!: Keep auth_time across id_token refresh - [`a1d78e3`](https://github.com/better-auth/better-auth/commit/a1d78e3fae47500b417572bd347efaa4e7faa414) Merge branch 'canary' into fix/refresh-auth-time - [`c35207e`](https://github.com/better-auth/better-auth/commit/c35207e1b2b0ebace43ab6a360e2354fc57ebdba) update docs - [`d4d8ad7`](https://github.com/better-auth/better-auth/commit/d4d8ad742725b2f87d66810953c9d423712f0ed1) convert to date - [`094ee97`](https://github.com/better-auth/better-auth/commit/094ee972cd971c40cf9320b6969df2b594374a20) fmt ### 📊 Changes **6 files changed** (+93 additions, -6 deletions) <details> <summary>View changed files</summary> 📝 `docs/content/docs/plugins/oauth-provider.mdx` (+6 -0) 📝 `packages/oauth-provider/src/authorize.ts` (+4 -0) 📝 `packages/oauth-provider/src/schema.ts` (+4 -0) 📝 `packages/oauth-provider/src/token.test.ts` (+43 -0) 📝 `packages/oauth-provider/src/token.ts` (+30 -6) 📝 `packages/oauth-provider/src/types/index.ts` (+6 -0) </details> ### 📄 Description - Fix auth_time claim in ID tokens to remain stable across refresh token grants, per https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse - Previously, auth_time was derived from ctx.context.session at token creation time, which falls back to "now" during refresh (no session in context), causing auth_time to drift on each refresh - Now auth_time is captured from the session during authorization, stored in the verification value, persisted on the refresh token record, and carried forward through rotation **Breaking changes** - Adds a new nullable authTime column to the oauthRefreshToken table (requires migration) - Existing refresh tokens will have authTime = NULL, in which case auth_time is omitted from the ID token <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Keeps auth_time in ID tokens stable across refresh, per OIDC Core 1.0 §12.2. Captures the original login time and carries it through token rotation so refreshed ID tokens keep the same auth_time. - **Bug Fixes** - Capture session.createdAt at authorization and include in the verification value. - Persist authTime on refresh tokens as a Date; read it on refresh and pass it to ID token creation. - Convert to seconds for the auth_time claim; omit when authTime is missing. - Added tests to confirm auth_time remains unchanged after refresh. - Documented the new authTime field in the oauthRefreshToken table. - **Migration** - Add a new nullable authTime (Date) column to oauthRefreshToken. - Existing refresh tokens will have authTime = NULL; refreshed ID tokens will omit auth_time until the user signs in again. <sup>Written for commit 094ee972cd971c40cf9320b6969df2b594374a20. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-13 10:21:03 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#16014