Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React SPA - Unable to logout user #1214

Open
tejasmudholkar opened this issue Apr 24, 2024 · 5 comments
Open

React SPA - Unable to logout user #1214

tejasmudholkar opened this issue Apr 24, 2024 · 5 comments
Labels
question Further information is requested

Comments

@tejasmudholkar
Copy link

tejasmudholkar commented Apr 24, 2024

I have a react application where I have integrated OIDC connect through react-oidc-context referring to installation instructions with some additions. I can Sign the user in the application. Doing so redirects me to the OIDC Sign-In screen, I fill in credentials, and then I am redirected back to my React SPA and my access token is available. All good so far. However, clicking Sign Out I am redirected to OP /logout. If I then navigate back in the browser I again get logged in without asking for credentials but if I refresh the screen then I get logged out.

Can you please help me with this?

My OIDC configuration

import { WebStorageStateStore } from "oidc-client-ts";

export const oidcConfig = {
 authority: window.ENV.AUTHORITY,
 client_id: window.ENV.CLIENT_ID,
 response_type: "code",
 scope: "openid offline groups builder.access",
 redirect_uri: `${window.location.origin}/callback`,
 post_logout_redirect_uri: `${window.location.origin}/logout`,
 automaticSilentRenew: false,
 revokeTokenTypes: ["access_token", "refresh_token"],
 revokeTokensOnSignout: true,
 userStore: new WebStorageStateStore({ store: window.sessionStorage }),
};

Here is my Login file

import { useAuth } from "react-oidc-context";
import "./Login.scss";
import Layout from "./Layout";
import { DefaultRoute } from "../routes";

export const Login = () => {
 const auth = useAuth();

 if (auth.error) {
  return (
   <div className="error">
    Oops something went wrong...
    <p>
     Refresh the browser and try again <br />
     <code> {auth.error.message}</code>
    </p>
   </div>
  );
 }

 if (auth.isLoading) {
  return <div className="loading">Loading...</div>;
 }

 if (auth.isAuthenticated) {
  return (
   <Layout>
    <DefaultRoute />
   </Layout>
  );
 } 
 
 if (!auth.isAuthenticated) {
  auth.signinRedirect();
 }

 return <></>;
};

export default Login;

Logout method to logout user

import { useAuth } from "react-oidc-context";

export const Logout = () => {
  const auth = useAuth();

  const handleLogout = () => {
    auth.removeUser();
    auth.signoutRedirect();
  };

  return (
    <>
      <button onClick={handleLogout}>Log Out user </button>
    </>
  );
};

I tried adding revokeTokenTypes: ["access_token", "refresh_token"], revokeTokensOnSignout: true properties in the oidc config file, but it didn't work. I expect the user to be logged out after logging out, and if he clicks the browser back button, he should not be led back to the application, but rather remain on the login screen.

@pamapa pamapa added the question Further information is requested label Apr 24, 2024
@pamapa
Copy link
Member

pamapa commented Apr 24, 2024

auth.removeUser(); returns a Promise, which you ignore, fixing that might solve your issue

@tejasmudholkar
Copy link
Author

tejasmudholkar commented Apr 29, 2024

Hi, @pamapa Thank you for responding. Could you please provide me with any references for the implementation you have suggested? It would be quite beneficial to me. Also, if I use this method:

  const handleLogout = () => {
    auth.removeUser();
    auth.signoutRedirect();
  };

I'm receiving the following error:

The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Logout failed because query parameter post_logout_redirect_uri is set but id_token_hint is missing.

@zach-betz-hln
Copy link

Your current code results in race between auth.removeUser() vs auth.signoutRedirect() since both calls return a promise.

You could try running the 2nd call only on the success of the first call.

auth
  .removeUser()
  .then(() => {
    void auth.signoutRedirect();
  })
  .catch((error) => {
    // Unable to remove user...
  });

@dszy579
Copy link

dszy579 commented May 15, 2024

Hi, @tejasmudholkar I'm experiencing the same issue. Did you manage to solve this issue?

@tejasmudholkar
Copy link
Author

tejasmudholkar commented May 23, 2024

Hi, @tejasmudholkar I'm experiencing the same issue. Did you manage to solve this issue?

Hi @dszy579 I did something similar, and it solved my problem.

const { user, removeUser, signoutRedirect, clearStaleState } = useAuth();

 const handleLogout = () => {
    removeUser();
    signoutRedirect({
      id_token_hint: user?.id_token,
    });
    clearStaleState();
  };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants