Skip to content

Fix: Back button after login causes "State not valid" error when user is already authenticated#1644

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-back-button-login-error
Draft

Fix: Back button after login causes "State not valid" error when user is already authenticated#1644
Copilot wants to merge 2 commits intomainfrom
copilot/fix-back-button-login-error

Conversation

Copy link
Contributor

Copilot AI commented Feb 24, 2026

When an IdP like Keycloak silently re-authenticates on browser back navigation, it redirects to the callback URL with a fresh state. Since the original state was already consumed after first login, the stored state is null, triggering State not valid (expected: null, received: XXXXX) and showing the error page.

Changes

  • packages/oidc-client/src/login.tsloginCallbackAsync
    • Capture the return value of serviceWorker.initAsync() (was previously discarded) to retrieve existing tokens from the service worker
    • For the non-SW path, call session.initAsync() to check for existing session tokens
    • On state mismatch: if oidc.tokens or stored tokens are present (user is already authenticated), log a warning and return early with existing tokens + stored callbackPath instead of throwing
    • If no tokens exist (unauthenticated), the original error is still thrown — security behavior is unchanged
if (queryParams.state && queryParams.state !== state) {
  if (oidc.tokens || existingTokens) {
    console.warn(`State not valid (...), but user is already authenticated, redirecting to callback path`);
    oidc.publishEvent(eventNames.loginCallbackAsync_end, {});
    return {
      tokens: oidc.tokens ?? existingTokens,
      state: 'request.state',
      callbackPath: getLoginParams?.callbackPath,
      ...
    };
  }
  throw new Error(`State not valid (expected: ${state}, received: ${queryParams.state})`);
}
  • packages/oidc-client/src/login.spec.ts — new test file covering:
    • State mismatch + oidc.tokens set → graceful redirect
    • State mismatch + session-stored tokens → graceful redirect
    • State mismatch + unauthenticated → error thrown (regression guard)
Original prompt

This section details on the original issue you should resolve

<issue_title>Back button after login cause an error : State not valid (expected: null, received: XXXXX)</issue_title>
<issue_description>We are using @axa-fr/react-oidc (7.26.3) with Keycloak and we're seeing an error page when hitting the back button after login :

state not found in service worker, using sessionStorage
Error: State not valid (expected: null, received: XXXXX)

Here's some details on the full flow :

  • User goes to app
  • App redirects to Keycloak
  • User logins into Keycloak
  • Keycloak redirect to callback_url with state=AAA
  • react-oidc validates the state and redirects the user to the landing page, user is connected
  • User press "back"
  • Browser returns to the Keycloak page
  • Keycloak sees the user has an active session and redirects to callback_url with a new state=BBB ⚠️ (I expect this to be the source of the issue)
  • react-oidc fails to validate the state "expected: null"
  • Error page is shown

This does not happen with your example because after pressing back Duende just shows the login form again;
Do you think this kind of use-case could be handled by the lib ?

Oidc config :

const oidcConfig: OidcConfiguration = {
  storage: window.localStorage,
  client_id: environment.oidc.clientId,
  redirect_uri: window.location.origin + '/auth/callback',
  silent_redirect_uri: window.location.origin + '/auth/silent-callback',
  scope: 'openid profile email offline_access', // offline_access scope allow your client to retrieve the refresh_token
  authority: environment.oidc.serverURL,
  service_worker_relative_url: '/OidcServiceWorker.js', // just comment that line to disable service worker mode
  service_worker_only: true,
  demonstrating_proof_of_possession: false, // demonstrating proof of possession will work only if access_token is accessible from the client (This is because WebCrypto API is not available inside a Service Worker)
};

</issue_description>

<agent_instructions>if user is already authenticated, an state error detected, we can just continue the flow and redirect to the expected url. </agent_instructions>

Comments on the Issue (you are @copilot in this section)

@guillaume-chervet Solutions are not simple on this issue. An idea can be if already authenticated, an state error detected, we can just continue the flow and redirect to the expected url. What do you think. @clementoriol ?

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@github-actions
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://black-rock-0dc6b0d03-1644.westeurope.1.azurestaticapps.net

@github-actions
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://icy-glacier-004ab4303-1644.westeurope.2.azurestaticapps.net

…ted (back button after login)

Co-authored-by: guillaume-chervet <52236059+guillaume-chervet@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix back button error after login state invalid Fix: Back button after login causes "State not valid" error when user is already authenticated Feb 24, 2026
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.

Back button after login cause an error : State not valid (expected: null, received: XXXXX)

2 participants