react-oidc-context
react-oidc-context copied to clipboard
Auth context is lost with react router
Hi, I use react v18, router v6 and this library. Without router everything works as expected however with router i have this problem that when i try to enter protected route /admin directly from browser then auth.isAuthenticated is false, but when I enter this path via <Naviage to="/admin">
then auth.isAuthenticated is still set to true. When I don't use RouteAuthGuard and enter directly to /admin then auth context is resolved from local storage but with RouteAuthGuard it seems that it can't resolve auth from local storage and auth is set to false.
function App() {
const router = createBrowserRouter([
{
path: "/",
element: <Home />,
},
{
path: "/admin",
element: <RouteAuthGuard component={<Admin />}></RouteAuthGuard>,
},
{
path: "/callback",
element: <AuthControl />,
},
]);
<RouterProvider router={router} />;
return <RouterProvider router={router} />;
}
export const RouteAuthGuard: React.FC<Props> = ({ component }) => {
const auth = useAuth();
const location = useLocation();
const navigate = useNavigate();
const context = React.useContext(AuthContext);
useEffect(() => {
if (!auth.isAuthenticated) {
// localStorage.setItem(PATH_LOCAL_STORAGE_KEY, location.pathname);
navigate("/home");
}
}, [auth.isAuthenticated]);
if (auth.isLoading) {
return <p>loading!</p>;
}
if (auth.error) {
throw new Error("unauthorized");
}
return <>{component}</>;
};
const AuthControl: React.FC = () => {
const navigate = useNavigate();
const auth = useAuth();
useEffect(() => {
if (auth.isAuthenticated) {
console.log(auth);
navigate("/");
}
}, [auth.isAuthenticated]);
if (!auth.isAuthenticated) {
return <div>Loading...</div>;
}
if (auth.error) {
return <div>Oops... {auth.error.message}</div>;
}
};
export default AuthControl;
export const oidcConfig = {
redirect_uri: `${window.location.origin}/callback`,
post_logout_redirect_uri: window.location.origin,
authority: "https://euc1.auth.ac/auth/realms/xxxxx",
client_id: "react-app",
response_type: "code",
automaticSilentRenew: true,
loadUserInfo: true,
triggerAuthFlow: true,
userStore: new WebStorageStateStore({ store: window.localStorage }),
};
any idea why?
make sure AuthProvider
comes before RouterProvider
@pamapa I used metadata key in the config to avoid using CORS and also have a redirection problem
export const oidcConfig = {
authority: GAS_BASE_URL,
client_id: process.env.REACT_APP_GAS_CLIENT_ID,
redirect_uri: process.env.REACT_APP_GAS_CALLBACK_URL,
scope: 'openid profile group_type email',
onSigninCallback: (user) => {
console.log('onsignin', user);
window.history.replaceState({}, document.title, '/');
window.location.reload();
},
userStore: new WebStorageStateStore({ store: window.localStorage }),
metadata: {
issuer: GAS_BASE_URL,
authorization_endpoint: GAS_BASE_URL + '/as/authorization.oauth2',
userinfo_endpoint: GAS_BASE_URL + '/idp/userinfo.openid',
end_session_endpoint: GAS_BASE_URL + 'idp/startSLO.ping'
}
};
log "onsignin" never fires. And in the console there is nothing but a warning: "No routes matched location "/callback?code=F8...78ca17e..asd".
The provider comes before Router:
root.render(
<AuthProvider {...oidcConfig}>
<BrowserRouter>
<Routes>
...
any ideas why redirection doesn't happen? Without metadata and with "CORS Unblock" extension everything works fine
UPDATED: Enabled logs and getting
Logger.ts:89 [OidcClient] readSigninResponseState: Error: No matching state found in storage
maybe a configuration is wrong, weird
UPDATED:
I added token_endpoint: GAS_BASE_URL + '/as/token.oauth2'
parameter, now it's just getting stuck on a callback page with a CORS error to this /as/token.oauth2
URL.
And I'm wondering, is it a bug in this lib or on an SSO authority side? Because in the docs oidc-client-ts it says: just add metadata to solve CORS issue. I added, didn't help :)
Logger.ts:89 [OidcClient] readSigninResponseState: Error: No matching state found in storage
That is the redirect callback call and it can somehow not match the data with the previously stored sigin request data, you will need to find out why...
Did you try using withAuthenticationRequired
? See README