This is my current implementation using react-router-dom, oidc-client-ts, react-oidc-context and keycloak authorization server
Have the following library versions
"oidc-client-ts": "^2.2.4", "react-oidc-context": "^2.2.2",
<Route path="/protected" element={ <AuthOidcProvider> <AuthBarrier> <AppLayout /> </AuthBarrier> </AuthOidcProvider> } > <Route path={HOME_PATH} element={<Home />} /> </Route>
AuthOidcProvider component is used to provide authentication context
interface AuthOidcProviderProps { children: ReactNode; } const AuthOidcProvider: FC<AuthOidcProviderProps> = ({ children, }): JSX.Element => { // const navigate = useNavigate(); const oidcConfig = { redirect_uri: OAUTH2_REDIRECT_URI, post_logout_redirect_uri: OAUTH2_POST_LOGOUT_REDIRECT_URI, silent_redirect_uri: OAUTH2_POST_LOGOUT_REDIRECT_URI, authority: OAUTH2_AUTHORITY, client_id: OAUTH2_CLIENT_ID, scope: "openid profile email", automaticSilentRenew: true, onSigninCallback() { // You must provide an implementation of onSigninCallback to oidcConfig to remove the payload // from the URL upon successful login. // Otherwise if you refresh the page and the payload is still there, signinSilent - which handles renewing your token - won't work. console.log("onSigninCallback()"); window.history.replaceState( {}, document.title, window.location.pathname ); }, }; return <AuthProvider {...oidcConfig}>{children}</AuthProvider>; }; export default AuthOidcProvider;
AuthBarrier component handles automatic authentication and blocks unauthenticated users
interface AuthBarrierProps { children: ReactElement; } // Automatically sign-in and silently reestablish your previous session, if you close the tab and reopen the application. const AuthBarrier: FC<AuthBarrierProps> = ({ children }): JSX.Element => { const auth = useAuth(); // automatically sign-in useEffect(() => { if ( !hasAuthParams() && !auth.isAuthenticated && !auth.activeNavigator && !auth.isLoading ) { auth.signinRedirect(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [ auth.isAuthenticated, auth.activeNavigator, auth.isLoading, auth.signinRedirect, ]); // // inactivity listener // useEffect(() => { // // the `return` is important - addAccessTokenExpiring() returns a cleanup function // return auth.events.addAccessTokenExpiring(() => { // console.log("Access token expiring..."); // // renew the access token silently // auth.signinSilent(); // console.log("Access token renewed."); // }); // // eslint-disable-next-line react-hooks/exhaustive-deps // }, [auth.events, auth.signinSilent]); switch (auth.activeNavigator) { case "signinSilent": console.log("signinSilent"); return <div>Signing you in...</div>; case "signoutRedirect": console.log("signoutRedirect"); return <div>Signing you out...</div>; } if (auth.isLoading) { return <LoadingAnimation />; } if (auth.error) { console.error(auth.error); return <LoadingAnimation />; } if (!auth.isAuthenticated) { return <LoadingAnimation />; } return <Fragment>{children}</Fragment>; }; export default AuthBarrier;
When I try to log out using auth.removeUser() I always get redirected to the "Home" page. In oidcConfig, post_logout_redirect_uri is invalid
Does anyone have an example of solving this problem?
I had the same problem and solved it by calling signoutRedirect() after removeUser():
The browser will redirect to the authentication server login page.
I used the same URI for post_logout_redirect_uri and redirect_uri.
Hope it helps.