[PR #7705] fix: getAccessToken does not refresh access token in stateless setup (#7703) #33104

Open
opened 2026-04-17 23:46:17 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/7705
Author: @biniam0
Created: 1/30/2026
Status: 🔄 Open

Base: mainHead: fix/stateless-get-access-token-refresh


📝 Commits (1)

  • f2c9b64 fix: getAccessToken refreshes token in stateless setup (fixes #7703)

📊 Changes

1 file changed (+11 additions, -6 deletions)

View changed files

📝 packages/better-auth/src/api/routes/account.ts (+11 -6)

📄 Description

Summary

Fixes #7703. In stateless (or cookie-cache) setups, calling getAccessToken when the access token was expired did not refresh the token and returned 400 BAD_REQUEST instead of a valid token.

Changes

  • Refresh when expiry is unknown: Attempt token refresh when we have a refresh token but no accessTokenExpiresAt (e.g. when the OAuth provider omits expires_in), so stateless and providers like Keycloak still get refreshed tokens.
  • Stateless-safe refresh: Wrapped updateAccount in try/catch. When it fails (e.g. no DB or account not in this instance’s store), we still return the new tokens and update the account cookie when storeAccountCookie is enabled, so the client gets a valid token.
  • Cookie matching: When resolving account from the cookie, match the request’s accountId to accountData.accountId (OAuth provider user id) instead of accountData.id (DB primary key), so getAccessToken({ providerId, accountId }) works when using the account cookie.

Testing

  • All 18 tests in packages/better-auth/src/api/routes/account.test.ts pass, including:
    • "should get access token using accountId from listAccounts"
    • "should refresh account_data cookie in stateless mode"
  • No API or config changes; existing behavior is preserved where a DB is used.

Summary by cubic

Fixes getAccessToken not refreshing in stateless/cookie-cache setups and returning 400. Tokens now refresh when expired or when expiry is missing, and cookie-based account matching uses accountId.

  • Bug Fixes
    • Refresh when a refresh token exists and the access token is expired or expiry is unknown; only when provider.refreshAccessToken is available.
    • Wrap updateAccount in try/catch; still return refreshed tokens and update the account cookie when storeAccountCookie is enabled, even if the DB update fails.
    • Match cookie account by accountId (provider user id) instead of DB id so getAccessToken({ providerId, accountId }) works with the account cookie.
    • No API or config changes.

Written for commit f2c9b64fce. 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/7705 **Author:** [@biniam0](https://github.com/biniam0) **Created:** 1/30/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/stateless-get-access-token-refresh` --- ### 📝 Commits (1) - [`f2c9b64`](https://github.com/better-auth/better-auth/commit/f2c9b64fcefef2495b2d93313ca714049471788e) fix: getAccessToken refreshes token in stateless setup (fixes #7703) ### 📊 Changes **1 file changed** (+11 additions, -6 deletions) <details> <summary>View changed files</summary> 📝 `packages/better-auth/src/api/routes/account.ts` (+11 -6) </details> ### 📄 Description ## Summary Fixes #7703. In stateless (or cookie-cache) setups, calling `getAccessToken` when the access token was expired did not refresh the token and returned 400 BAD_REQUEST instead of a valid token. ## Changes - **Refresh when expiry is unknown:** Attempt token refresh when we have a refresh token but no `accessTokenExpiresAt` (e.g. when the OAuth provider omits `expires_in`), so stateless and providers like Keycloak still get refreshed tokens. - **Stateless-safe refresh:** Wrapped `updateAccount` in try/catch. When it fails (e.g. no DB or account not in this instance’s store), we still return the new tokens and update the account cookie when `storeAccountCookie` is enabled, so the client gets a valid token. - **Cookie matching:** When resolving account from the cookie, match the request’s `accountId` to `accountData.accountId` (OAuth provider user id) instead of `accountData.id` (DB primary key), so `getAccessToken({ providerId, accountId })` works when using the account cookie. ## Testing - All 18 tests in `packages/better-auth/src/api/routes/account.test.ts` pass, including: - "should get access token using accountId from listAccounts" - "should refresh account_data cookie in stateless mode" - No API or config changes; existing behavior is preserved where a DB is used. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Fixes getAccessToken not refreshing in stateless/cookie-cache setups and returning 400. Tokens now refresh when expired or when expiry is missing, and cookie-based account matching uses accountId. - **Bug Fixes** - Refresh when a refresh token exists and the access token is expired or expiry is unknown; only when `provider.refreshAccessToken` is available. - Wrap `updateAccount` in try/catch; still return refreshed tokens and update the account cookie when `storeAccountCookie` is enabled, even if the DB update fails. - Match cookie account by `accountId` (provider user id) instead of DB id so `getAccessToken({ providerId, accountId })` works with the account cookie. - No API or config changes. <sup>Written for commit f2c9b64fcefef2495b2d93313ca714049471788e. 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-17 23:46:18 -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#33104