okta/okta-react

Question on implementation approach

tantilla opened this issue · 7 comments

I'm submitting a:

  • Bug report
  • Feature request
  • [ *] Other (Describe below)
    Question

Current behavior

Expected behavior

Minimal reproduction of the problem with instructions

Extra information about the use case/user story you are trying to implement

Environment

  • Package version:
  • React version:
  • Browser:
  • OS:
  • Node version (node -v):
  • Other:

Configuration

  • Okta application type: React / web

Hello,
Sorry for posting a question here, not getting responses in the forum.

I’m using a typical PKCE hosted login setup based on the okta-react hosted login demo, initialized once at the top of the app with a switch and secure routes.

“@okta/okta-auth-js”: “~5.10.1”,
“@okta/okta-react”: “~6.4.1”

For the most part everything is working as as expected, but a few times a month users (oddly only in the east coast region) get redirected to the login page from their secure route, interrupting their work session. I implemented an error component expecting to log evidence of some session issue there but so far the users have not reported error screens. Htttp archive files just show intermittent redirects to the hosted login.

Our users now want a guarantee that they can perform some actions before they are redirected, like a warning dialog with local storage save options - regardless of whether the redirect is triggered by standard session expiration or some exception in the core library.

Without having yet examined the okta-react or okta-auth-js source, is there a supported / recommended approach to add some kind of redirect guard, or is the window location being manipulated somewhere without options so the redirect cannot be blocked by anything via API, in which case implementing a custom component wrapping the core library would be necessary ?

@tantilla do you happen to know if the users experiencing these issues are using multiple tabs?

Yes they are nearly always using multiple tabs.

We are currently investigating an intermittent issue when users have multiple tabs open simultaneously. The scenario you described seems to match. Could you provide a minimum code sample or git repo which reproduces the issue so we can confirm?

To be clear, I have not been able to reproduce the issue personally, even after leaving the application open all day. Its only via user's videos and logs that I've seen any evidence of issues. I am beggining to collect browser information. At any rate, though I doubt it's helpful, below is the basic auth pattern we use in all our applications.

If you think only instantiating one running core Okta-js instance, instead of one in every tab, would improve session stability, perhaps deriving a secondary auth API for new tabs, that just queries the tokens, etc. set in storage by the singleton auth instance in the main application might be a reasonable approach...

import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js';
import { LoginCallback, SecureRoute, Security, useOktaAuth } from '@okta/okta-react';
import { history } from 'core';
import React, { useEffect, useState } from 'react';
import { Route, Router, Switch } from 'react-router-dom';

const { REACT_APP_ISSUER, REACT_APP_CLIENT_ID } = process.env
if (!REACT_APP_ISSUER || !REACT_APP_CLIENT_ID) {
  throw `Missing Okta Configuration`;
}
const okta = new OktaAuth({
  issuer: REACT_APP_ISSUER,
  clientId: REACT_APP_CLIENT_ID,
  redirectUri: window.location.origin + '/login/callback',
  pkce: true,
  tokenManager: {
    autoRenew: true
  }
});

okta.authStateManager.subscribe((a: any) => {
  console.log('State change accessToken)', a.accessToken?.accessToken);
});
okta.tokenManager.on('expired', (key, expiredToken) => {
  console.log('Token with key', key, ' has expired:', expiredToken);
});
okta.tokenManager.on('renewed', function (key, newToken, oldToken) {
  console.log('Token with key', key, 'has been renewed', oldToken, newToken);
});
okta.tokenManager.on('error', function (err) {
  console.log('TokenManager error:', err);
});

const Home = () => {
  const { authState, oktaAuth } = useOktaAuth();
  const [userInfo, setUserInfo] = useState(null);

  useEffect(() => {
    if (!authState || !authState.isAuthenticated) {
      setUserInfo(null);
    } else {
      oktaAuth.getUser().then((info) => {
        setUserInfo(info);
      }).catch((err) => {
        console.error(err);
      });
    }
  }, [authState, oktaAuth]); // Update if authState changes

  const login = async () => {
    oktaAuth.signInWithRedirect({ originalUri: '/' });
  };

  useEffect(() => {
    if (!authState?.isAuthenticated) {
      login()
    }
  }, [])

  if (!authState) {
    return (
      <div>Loading...</div>
    );
  }

  return (
    <div >
      <div>
        {authState?.isAuthenticated &&
          <p>
            <a href='/admin'>To Admin</a>
          </p>
        }

        <div>
          User
          <p>
            {
              <div style={{ width: '70vw', whiteSpace: 'pre-wrap', fontSize: 9, wordWrap: 'break-word' }}>{JSON.stringify(userInfo || {}, null, 1)}</div>
            }
          </p>

        </div>

        <div>
          Auth State
          <p>
            {
              <div style={{ width: '70vw', whiteSpace: 'pre-wrap', fontSize: 9, wordWrap: 'break-word' }}>{JSON.stringify(authState || {}, null, 1)}</div>
            }
          </p>
        </div>
      </div>
    </div>
  );
};

function App() {
  const restoreOriginalUri = async (_oktaAuth: any, originalUri: any) => {
    history.replace(toRelativeUrl(originalUri || '/', window.location.origin));
  };

  return (
    <Security oktaAuth={okta} restoreOriginalUri={restoreOriginalUri}>
      <Router history={history}>
        <Switch>
          <Route path='/' exact component={Home} />
          <Route path='/login/callback' exact component={LoginCallback} />
          <SecureRoute path='/admin' exact>
            Admin
          </SecureRoute>
        </Switch>
      </Router>
    </Security>
  )
}
export default App;

I've been encountering this same thing for over a year now. Not using multiple tabs. Just all of a sudden, me and other users get kicked to the login page for seemingly no reason.

hi @chinanderm

Did you ever find out what was causing this issue? I'm also not using multiple tabs and am experiencing the same issue.

@jwmke Unfortunately no. I moved away from using the Okta React library and am using their raw JS library instead, building the functionality I need myself.