LibreChat/api/server/services
Claude e0f56b17c8
🔒 fix: Refresh MCP OBO Tokens From the Live OpenID Session
Merge jcbartle's #13901 up to date with main (307 commits since its last
merge at 5ff282f90) and reconcile it with what landed in the meantime.

OBO exchange read `user.federatedTokens`, the snapshot captured at strategy
time, so a user who idled past their access-token lifetime got "No valid
OpenID access token is available for OBO exchange" while a still-refreshable
token sat unread in `req.session.openidTokens` (#13899). Exchange now reads
the live server-side session at MCP call time and refreshes the upstream
token inline, single-flighted across workers through a Mongo refresh-flight
record, with an encrypted bridge so a token rotated mid-SSE stream (headers
already sent, cookie unwritable) stays recoverable on the next /refresh.

Reconciled against main:

- Exchanged-token cache TTLs now carry the in-transit expiry buffer (#15320).
  The PR's `mcp/oauth/expiry.ts` and main's `oauth/expiry.ts` (#15321) were
  two homes for the same arithmetic; they are now one. `getTokenCacheTtlMs`
  subtracts `OPENID_EXPIRY_BUFFER_SECONDS`, which also covers the Graph and
  openidStrategy caches, and the skew helpers build on main's
  `normalizeExpiresIn` so an elapsed lifetime still stays elapsed.
  `OPENID_EXPIRY_BUFFER_SECONDS` moves to `oauth/expiry.ts`, where the rest
  of the lifetime math lives: consumers that stub `~/utils/oidc` were
  leaving the arithmetic reading `undefined`.
- The `openid_user_id` marker keeps the refresh-token binding main added in
  #15252, now inside the shared `setOpenIDMarkerCookies` helper so the
  inline-refresh path produces the same bound cookie as login.
- Every OpenID token issuance in `refreshController` — including bridge
  recovery, which previously issued tokens without one — persists the
  durable Session record through `sendOpenIDAuthResponse`.
- An inline refresh that rotates the token and writes the cookie moves the
  durable Session record with it. Local image access for OpenID users is
  authorized by that record keyed on the browser's cookie, so leaving it
  behind 401s every image until the next /refresh. The bridge path
  deliberately leaves it alone: there the browser keeps the old cookie.

Co-authored-by: jcbartle <7274202+jcbartle@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SxKWxwqxAGckYpRsYTqx3F
2026-08-29 13:40:21 +00:00
..
__tests__ 🔌 feat: Background Execution Toggles for Actions & Plugin Tools (#14407) 2026-08-25 08:13:13 -04:00
Agents 🪧 fix: Advertise Detached Event Actor Support from the Generation Store (#15322) 2026-08-28 16:33:23 -04:00
Artifacts 🧵 fix: Preserve Fenced Markdown Artifacts (#14121) 2026-07-05 12:04:59 -04:00
Config 🌐 fix: Expose Gemini Models to Vertex AI Agents (#15234) 2026-08-27 06:50:23 -04:00
Endpoints 🪂 feat: Make Event Actor Detached Actions Durable (#15307) 2026-08-28 14:21:04 -04:00
Files 📨 feat: Continue Bound Child Agents from Events (#15112) 2026-08-23 01:15:57 -04:00
Runs 🛂 feat: Filter Model-Bound Content by Source (#14425) 2026-08-21 22:43:32 -04:00
Schedules 🗂️ feat: Scope Scheduled Chats to Chat Projects (#15056) 2026-08-21 11:09:04 -04:00
Skills 🧬 feat: Add GitHub Skill Sync (#13293) 2026-06-10 21:05:54 -04:00
start 🙋 feat: ask_user_question - agent-initiated questions with durable pause/resume (#14139) 2026-07-08 15:31:05 -04:00
Threads 🧾 fix: Honor Disabled Transactions on the Assistants Usage Path (#15100) 2026-08-25 08:30:12 -04:00
Tools 🔒 fix: Refresh MCP OBO Tokens From the Live OpenID Session 2026-08-29 13:40:21 +00:00
ActionService.js 🕰️ fix: Guard expires_in So a Token Response Cannot Outlive Its Credential (#15321) 2026-08-28 10:47:09 -04:00
ActionService.spec.js 🛂 test: Cover Tool Approval Workflows End to End (#14427) 2026-07-26 21:58:25 -04:00
AssistantService.js 🛂 feat: Filter Model-Bound Content by Source (#14425) 2026-08-21 22:43:32 -04:00
AuthService.js 🔒 fix: Refresh MCP OBO Tokens From the Live OpenID Session 2026-08-29 13:40:21 +00:00
AuthService.spec.js 🔒 fix: Refresh MCP OBO Tokens From the Live OpenID Session 2026-08-29 13:40:21 +00:00
cleanup.js
createRunBody.js 🛂 feat: Filter Model-Bound Content by Source (#14425) 2026-08-21 22:43:32 -04:00
createRunBody.spec.js 🛂 feat: Filter Model-Bound Content by Source (#14425) 2026-08-21 22:43:32 -04:00
GraphApiService.js 🕰️ fix: Guard expires_in So a Token Response Cannot Outlive Its Credential (#15321) 2026-08-28 10:47:09 -04:00
GraphApiService.spec.js
GraphTokenService.js
initializeMCPs.js 🔌 feat: Add Agent Plugins (Experimental) (#14704) 2026-08-09 08:10:22 -04:00
initializeMCPs.plugins.spec.js 🔌 feat: Add Agent Plugins (Experimental) (#14704) 2026-08-09 08:10:22 -04:00
initializeMCPs.spec.js 🔌 feat: Add Agent Plugins (Experimental) (#14704) 2026-08-09 08:10:22 -04:00
initializeOAuthReconnectManager.js
MCP.js 🔒 fix: Refresh MCP OBO Tokens From the Live OpenID Session 2026-08-29 13:40:21 +00:00
MCP.spec.js 🔒 fix: Refresh MCP OBO Tokens From the Live OpenID Session 2026-08-29 13:40:21 +00:00
MCPRequestContext.js 🪢 fix: Tie MCP Cleanup To Resumable Runs (#13769) 2026-06-15 15:26:03 -04:00
OboPolicyService.js
OboTokenService.js 🔒 fix: Refresh MCP OBO Tokens From the Live OpenID Session 2026-08-29 13:40:21 +00:00
OboTokenService.spec.js 🛠️ fix: Harden OBO token caching and expiry handling 2026-06-28 19:19:51 -04:00
OpenIDRefreshFlight.js 🛠️ fix: centralize OBO identity scoping 2026-06-28 10:39:04 -04:00
OpenIDRefreshFlight.spec.js 🛠️ fix: centralize OBO identity scoping 2026-06-28 10:39:04 -04:00
OpenIDSessionRefresh.js 🔒 fix: Refresh MCP OBO Tokens From the Live OpenID Session 2026-08-29 13:40:21 +00:00
OpenIDSessionRefresh.spec.js 🔒 fix: Refresh MCP OBO Tokens From the Live OpenID Session 2026-08-29 13:40:21 +00:00
PermissionService.js perf: Avoid Parallel Full and Paged Prompt Loading on Startup (#15031) 2026-08-25 21:21:17 -04:00
PermissionService.spec.js perf: Agent List and Model Selector at Scale (#14601) 2026-08-07 21:04:55 -04:00
PluginService.js 🕸️ feat: Complete Keenable Web Search Provider (#15288) 2026-08-27 14:29:20 -04:00
PluginService.spec.js 🕸️ feat: Complete Keenable Web Search Provider (#15288) 2026-08-27 14:29:20 -04:00
RefreshTokenBridge.js 🛠️ fix: Harden OBO refresh-token bridge lookup and indexing 2026-06-28 19:57:50 -04:00
RefreshTokenBridge.spec.js 🛠️ fix: Harden OBO refresh-token bridge lookup and indexing 2026-06-28 19:57:50 -04:00
systemGrant.spec.js
ToolService.js 🔒 fix: Refresh MCP OBO Tokens From the Live OpenID Session 2026-08-29 13:40:21 +00:00
twoFactorService.js 🥁 fix: Compare TOTP Codes in Constant Time (#15157) 2026-08-24 09:10:03 -04:00
twoFactorService.spec.js 🥁 fix: Compare TOTP Codes in Constant Time (#15157) 2026-08-24 09:10:03 -04:00