I have a react app with a weird bug. If it logs out and goes to the login page in chrome, it doesn’t restore back to the previous uri. In fact the originalUri in my restoreOriginalUri callback is undefined. However if the same thing happens in another browser (firefox, safari, etc), the original uri is the prior uri visited.
this is my may app code. I’m using react-router-dom v6 so I have to handle my own route authorization:
__webpack_nonce__ = window.nonce
import { Fragment, lazy, Suspense, useCallback, useRef, useEffect } from 'react';
import { Routes, Route, useNavigate, useLocation, Navigate } from 'react-router-dom';
import { Security, LoginCallback } from '@okta/okta-react';
import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js';
import createCache from '@emotion/cache';
import { RequireAuth } from './apps/Main/components/SecureRoute';
import Home from './apps/Main/Home';
import Login from './apps/Main/Login';
const cache = createCache({
key: 'some-dang-key',
nonce: __webpack_nonce__,
prepend: true,
});
const storageType = 'sessionStorage';
const config = {
issuer: process.env.OKTA_ISSUER,
clientId: process.env.OKTA_CLIENT_ID,
redirectUri: window.location.origin + '/oidc/callback',
scopes: ['openid', 'profile', 'email', 'offline_access'],
tokenManager: {
autoRenew: false,
storage: storageType
},
services: {
autoRenew: false
},
pkce: true
}
const PageNotFound404 = (props) => {
console.log(window.location.href);
return (
<div>
<h1>404 - Not found</h1>
<h3>(I promise this will look nice someday.)</h3>
</div>
);
};
const Dash = (props) => {
return (
<div
style={{
backgroundColor: "orange"
}}
>
Hello
</div>
)
}
function App() {
const oktaAuth = new OktaAuth(config);
const navigate = useNavigate();
const navigateRef = useRef(navigate)
const restoreOriginalUri = async (_oktaAuth, originalUri) => {
console.log(originalUri); // comes up as undefined in chrome
let go_to_this = toRelativeUrl(originalUri || '/home', window.location.origin);
console.log(go_to_this);
navigate(go_to_this);
};
return (
<Security
oktaAuth={oktaAuth}
restoreOriginalUri={restoreOriginalUri}
>
<Routes>
<Route path='' element={<RequireAuth />}>
<Route path="/" element={<Navigate to="/home" replace />} />
<Route path='/home' element={<Home />} />
<Route path='/dashboard' element={<Dash />} />
</Route>
<Route path='/login/:redirect?' element={<Login />} />
<Route path='/oidc/callback' element={<LoginCallback />} />
<Route path='*' element={<PageNotFound404 />} />
</Routes>
</Security>
)
}
export default App;
This is the code for the secure route:
import { useEffect, useState } from "react";
import { useOktaAuth } from "@okta/okta-react";
import { Outlet, Navigate } from "react-router-dom";
import { toRelativeUrl } from '@okta/okta-auth-js';
/*
This is causing a double load of the authenticated route. I think
it may have something to do with the state trigger - one thing happening
and then happening again once state catches up. Need to address.
*/
export const RequireAuth = () => {
const { oktaAuth, authState } = useOktaAuth();
const [ notLoggedIn, setNotLoggedIn ] = useState(false);
useEffect(() => {
if (!authState) {
return;
}
if (!authState?.isAuthenticated) {
setNotLoggedIn(true);
let originalUri = toRelativeUrl(window.location.href, window.location.origin);
console.log(originalUri); // shows the correct redirect uri here. somehwere along the way it becomes undefined.
oktaAuth.setOriginalUri(originalUri);
} else {
setNotLoggedIn(false)
}
}, [!!authState, authState?.isAuthenticated]);
if (!authState || !authState?.isAuthenticated) {
if (notLoggedIn) {
return <Navigate to='/login' replace={true} />
} else {
return;
}
}
return <Outlet />
}
As a test I created the secure route /dashboard that i try to navigate to after I log out. It goes to the login page and says that the original uri is set to “/dashboard”. Once I initiate the authorization flow the uri is somehow purged but only in Chrome it seems.
Does the loginCallback process re-initialize the uri to undefined? It’s the only thing I can think of but I can’t explain why it works for other browsers.
Any thoughts?
Thanks!
-Mark