oidc-client icon indicating copy to clipboard operation
oidc-client copied to clipboard

Sessions lost/timed out when using multiple browser tabs

Open richcatt opened this issue 1 year ago • 12 comments

Issue and Steps to Reproduce

In a multiple tabbed scenario for the same SPA application, sessions are not being renewed correctly.

I have tried switching the token storage to local as a workaround but the issue persists.

I've also looked at ignoring the session lost event or adding a redirect/reload but no luck.

Versions

6.16.9

Screenshots

image

Expected

Sessions should be renewed across all tabs silently

Actual

Sessions are expiring - storage shows one of the following for the oidc.default key:

{"tokens":null,"status":null} {"tokens":null,"status":"LOGGED_OUT"}

If using session storage, the following is shown:

{"tokens":null,"status":"SESSION_LOST"}

Additional Details

The web worker doesn't seem to be registered - not sure if this is relevant here but thought I'd mention it!

richcatt avatar Mar 30 '23 09:03 richcatt

Hi @cattre ,

Thank you for your issue. Do you have a sample of you configuration?

guillaume-chervet avatar Mar 30 '23 12:03 guillaume-chervet

Hi @guillaume-chervet,

Thanks for the quick reply (and for the library, which is great!).

I've got it working now, but only after downgrading to v6.14.8 - does this help at all? Let me know what other config you need to see.

Also, is local storage the only option for this use case?

richcatt avatar Mar 30 '23 12:03 richcatt

Hi @cattre , it should works with localstorage or with serviceworker mode.

Do you use service worker ?

guillaume-chervet avatar Apr 02 '23 13:04 guillaume-chervet

Hi @guillaume-chervet, we have the service worker files but it doesn't look it's being used (nothing showing as registered in dev tools).

I think for our requirements (accessing the token within js), localstorage is probably the best option so we'll still with that for now. Do you know any reason for this not to work in the latest version though?

richcatt avatar Apr 04 '23 08:04 richcatt

Hi @cattre do you have a sample of your configuration. It will help me to help you more.

guillaume-chervet avatar Apr 04 '23 10:04 guillaume-chervet

@guillaume-chervet I can't share the whole app but these are the main parts I guess:

export const IDENTITY_CONFIG = {
  authority: rootPath,
  client_id: clientId,
  redirect_uri: rootPath + basePath + '/signin-oidc',
  silent_redirect_uri: rootPath + basePath + '/silent-renew',
  scope: 'openid offline_access',
  automaticSilentRenew: true,
  storage: localStorage
}

<OidcProvider configuration={IDENTITY_CONFIG}
                        loadingComponent={Loading}
                        authenticatingErrorComponent={AuthError}
                        authenticatingComponent={Loading}
                        callbackSuccessComponent={Loading}
          >
  <App />
</OidcProvider>

richcatt avatar Apr 04 '23 10:04 richcatt

Hi @cattre ,

I cannot reproduce your issue copying the your configuration using the demo. Does your oidc server is inside the same domain than your application?

If you use your configuration with the demo. https://black-rock-0dc6b0d03.1.azurestaticapps.net/ May you send me the logs? in order to understand what happenning?

guillaume-chervet avatar Apr 04 '23 13:04 guillaume-chervet

I am able to reproduce this.

Create a new React app, and install this library

npx create-react-app --template cra-template-typescript .
npm install --save @axa-fr/react-oidc

Then modify src/index.tsx:

diff --git a/src/index.tsx b/src/index.tsx
index 032464f..e00635d 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,5 +1,6 @@
 import React from 'react';
 import ReactDOM from 'react-dom/client';
+import { OidcProvider, OidcSecure } from '@axa-fr/react-oidc';
 import './index.css';
 import App from './App';
 import reportWebVitals from './reportWebVitals';
@@ -7,9 +8,23 @@ import reportWebVitals from './reportWebVitals';
 const root = ReactDOM.createRoot(
   document.getElementById('root') as HTMLElement
 );
+const configuration = {
+  authority: 'https://auth.example.com',
+  client_id: 'client-id',
+  redirect_uri: `${window.location.origin}/authentication/callback`,
+  silent_redirect_uri: `${window.location.origin}/authentication/silent-callback`,
+  scope: 'openid',
+};
 root.render(
   <React.StrictMode>
-    <App />
+    <OidcProvider
+      configuration={configuration}
+      onEvent={(name, data) => console.log({ name, data }, 'OidcProvider event')}
+    >
+      <OidcSecure>
+        <p>Hello, world</p>
+      </OidcSecure>
+    </OidcProvider>
   </React.StrictMode>
 );

Run npm run start, and open a second tab to the same location. After the first access token expires, the first tab should show the session lost component.

Additionally, the console log shows:

Object { name: "default", data: "refreshTokensAsync" }
 OidcProvider event index.tsx:22
Object { name: "default", data: "refreshTokensAsync_begin" }
 OidcProvider event index.tsx:22
Object { name: "default", data: "refreshTokensAsync_error" }
 OidcProvider event index.tsx:22

In case it matters, I am using Keycloak 20.0.1 as my IdP. I observed the same behavior in Firefox 110.0.1 and Chromium 111.0.5563.146.

jasonaowen avatar Apr 05 '23 02:04 jasonaowen

Hi @jasonaowen , very sorry i missed you message. I will try to reproduce it quickly so i will be able to fix it.

guillaume-chervet avatar May 05 '23 20:05 guillaume-chervet

Thank you, @guillaume-chervet! No apology needed; I appreciate you maintaining this wonderful tool.

jasonaowen avatar May 05 '23 22:05 jasonaowen

Hi @jasonaowen @richcatt , i set the same configuration on the demo using dudende oidc server and i cannot reproduce the error. Which oidc server are you using?

guillaume-chervet avatar May 10 '23 19:05 guillaume-chervet

@guillaume-chervet I am using Keycloak, but I was also able to reproduce it with the demo Duende server:

@@ -7,9 +8,23 @@ import reportWebVitals from './reportWebVitals';
 const root = ReactDOM.createRoot(
   document.getElementById('root') as HTMLElement
 );
+const configuration = {
+  authority: 'https://demo.duendesoftware.com/',
+  client_id: 'interactive.public.short',
+  redirect_uri: `${window.location.origin}/authentication/callback`,
+  silent_redirect_uri: `${window.location.origin}/authentication/silent-callback`,
+  scope: 'openid',
+};
 root.render(
   <React.StrictMode>
-    <App />
+    <OidcProvider
+      configuration={configuration}
+      onEvent={(name, data) => console.log({ name, data }, 'OidcProvider event')}
+    >
+      <OidcSecure>
+        <p>Hello, world</p>
+      </OidcSecure>
+    </OidcProvider>
   </React.StrictMode>
 );

Interestingly, while I can still reproduce this on Firefox 112.0, I can no longer reproduce it in Chromium 112.0.5615.49. Unfortunately, the Chrome change log for that version range is a bit overwhelming, and I am not currently set up to install specific commits or even older versions to figure out what changed.

jasonaowen avatar May 10 '23 19:05 jasonaowen