Skip to content

fix: clear unusable OpenID refresh tokens when reuse is disabled#95

Open
dvorak33 wants to merge 1 commit into
ClickHouse:mainfrom
dvorak33:fix/openid-refresh-token-reuse-disabled
Open

fix: clear unusable OpenID refresh tokens when reuse is disabled#95
dvorak33 wants to merge 1 commit into
ClickHouse:mainfrom
dvorak33:fix/openid-refresh-token-reuse-disabled

Conversation

@dvorak33

@dvorak33 dvorak33 commented Jul 6, 2026

Copy link
Copy Markdown

Summary

I fixed the admin panel's handling of unusable OpenID refresh tokens when the LibreChat deployment has OPENID_REUSE_TOKENS=false. Before this change, the BFF stored the IdP refresh token returned by /api/admin/oauth/exchange and kept retrying it against /api/admin/oauth/refresh even though the backend correctly rejects every call with 403 TOKEN_REUSE_DISABLED.

  • Modeled refresh calls as a discriminated RefreshOutcome (success / reuse_disabled / failed) so callers can distinguish a policy signal from a plain failure without losing type safety.
  • Detected 403 TOKEN_REUSE_DISABLED from /api/admin/oauth/refresh and cleared the stored refreshToken from the session in ensureFreshBearer, refreshOn401, and the verifyAdminTokenFn 401-recovery path.
  • Dropped the OpenID cookie fallback in oauthExchangeFn so a missing refreshToken in the exchange body is stored as undefined instead of an unrelated cookie value.
  • Added focused tests for the missing exchange refresh token and for TOKEN_REUSE_DISABLED handling in each caller.
  • Fixes Avoid retaining unusable OpenID refresh tokens when reuse is disabled #47.

OPENID_REUSE_TOKENS=true behavior is unchanged: the success outcome flows through exactly as before, including refresh-token rotation and dedupe.

Change Type

  • Bug fix (non-breaking change which fixes an issue)

Testing

  • npx vitest run src/server/utils/refresh.test.ts src/server/auth.oauth.test.ts — 32/32 pass
  • npx eslint src/server/auth.ts src/server/utils/refresh.ts src/server/utils/refresh.test.ts src/server/auth.oauth.test.ts — clean
  • npx tsc --noEmit — clean

Test Configuration

  • Node.js v24
  • Vitest 4.1.9

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective
  • Local unit tests pass with my changes

The admin panel BFF stored the IdP refresh token returned by
`/api/admin/oauth/exchange` and kept retrying it against
`/api/admin/oauth/refresh` even when the deployment has
`OPENID_REUSE_TOKENS=false`. The backend correctly rejects that call with
`403 TOKEN_REUSE_DISABLED`, but the token stayed in session state and the
refresh loop kept firing.

- Model refresh calls as a discriminated `RefreshOutcome`
  (`success` / `reuse_disabled` / `failed`) so callers can distinguish a
  policy signal from a plain failure.
- Detect `403 TOKEN_REUSE_DISABLED` from `/api/admin/oauth/refresh` and
  clear the stored `refreshToken` from the session in `ensureFreshBearer`,
  `refreshOn401`, and the `verifyAdminTokenFn` 401-recovery path.
- Drop the openid cookie fallback in `oauthExchangeFn` so a missing
  `refreshToken` in the exchange body is stored as `undefined` instead of
  a stale value.
- Add focused tests for the missing exchange refresh token and the
  `TOKEN_REUSE_DISABLED` handling in each caller.

Fixes ClickHouse#47.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

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.

Avoid retaining unusable OpenID refresh tokens when reuse is disabled

2 participants