---
title: "Connection: OAuth State Mismatch — LibreChat vs MSAL SPA"
connects:
  - "concepts/librechat-openid-auth"
  - "concepts/msal-vanilla-js-pkce"
  - "tech-patterns/azure-ad-msal-auth"
sources:
  - "daily/2026-04-15.md"
created: 2026-04-15
updated: 2026-04-15
---

# Connection: OAuth State Mismatch — LibreChat vs MSAL SPA

## The Connection

Both LibreChat's built-in OpenID integration and custom MSAL.js SPA implementations use Azure AD OAuth with state validation. OAuth state mismatch — where the `state` parameter returned by Azure doesn't match what's in the session — manifests very differently in each system but has the same root causes.

## Key Insight

In LibreChat, a state mismatch surfaces as `Unknown OAuth error` (the session message array is empty). In a custom MSAL.js SPA, a state mismatch surfaces as a silent redirect to an error page or a blank callback. In both cases, the fix is at the **session layer** (clear stale cookies, try a different browser), not in Azure AD configuration. This is non-obvious because the error points away from the actual cause.

The shared root cause: if the server restarts between OAuth initiation (`/oauth/openid`) and the callback (`/oauth/callback`), the session store loses the original state. Azure sends back the correct state, but the server-side session no longer has it to compare against — the check fails.

## Evidence

- **LibreChat (2026-04-15):** User `santhosha.nayak@brandtech.plus` could not log in. Microsoft auth succeeded (user saw Microsoft login, approved it). LibreChat showed `Unknown OAuth error`. Network tab showed: `302 → /oauth/openid → Microsoft OK → /oauth/callback → /oauth/error`. Root cause: stale session cookie from a previous attempt after server restart. Resolution path: try different browser / clear cookies.
- **MSAL SPA (2026-04-15):** MSAL.js v5 UMD in a plain-HTML dashboard. MSAL handles state internally via `sessionStorage`. If `sessionStorage` is cleared between initiation and callback (e.g., navigation, redirect loops), MSAL throws a state mismatch error client-side. MSAL's internal handling is more transparent than LibreChat's.

## Diagnostic Heuristic

When OAuth fails after Microsoft auth succeeds:

1. Check if this is a first attempt or a retry — retries are more likely to hit state mismatch
2. Check if the server recently restarted
3. Try from a different browser / incognito window
4. Only then investigate Azure AD app registration, Conditional Access, or account status

## Related Concepts

- [[wiki/concepts/librechat-openid-auth]] — LibreChat-specific auth internals and ALLOW_SOCIAL_REGISTRATION
- [[wiki/concepts/msal-vanilla-js-pkce]] — MSAL.js v5 UMD SPA implementation
- [[wiki/tech-patterns/azure-ad-msal-auth]] — Azure AD patterns across Oliver projects
