React-admin: AUTH_CHECK doesn't change state isLoggedIn

Created on 27 Jun 2018  路  5Comments  路  Source: marmelab/react-admin

What you were expecting:
If a user is loggedIn and refreshes the page its session must be preserved, and redux state must not change isLoggedIn, or change it to true if AUTH_CHECK promise resolves

What happened instead:
When a user is logged and refreshes the page, redux store is cleared making state back to default, isLoggedIn defaults to false. Even with the USER_CHECK action being dispatched on route changes this only checks if the promise of authProvider resolves successfully not changing any state.

Steps to reproduce:
Not sure if it will reproduce the bug correctly but the following can be done:

  1. Create and app with:

    • Custom Dashboard, might be an empty page just for have a landing page that requires no authentication

    • Custom dataProvider that saves a token in localStorage, and promise resolves in AUTH_CHECK if token is available

    • Custom Menu that only show resources if user is loggedIn

  2. Go to dashboard and not see resources
  3. LogIn
  4. Now is possible to see resources
  5. Refresh page
  6. Resources are again not available but USER_CHECK resolves successfully

Related code:

//In Menu.js function component
<div>
    <MenuItemLink
      to="/dashboard"
      primaryText="Dashboard"
      leftIcon={<DashboardIcon/>}
      onClick={onMenuClick}
/>
{isLoggedIn ?
    {resources.map(resource => (
      <MenuItemLink
        key={resource.name}
        to={`/${resource.name}`}
        primaryText={translate(`resources.${resource.name}.name`, { smart_count: 2 })}
        onClick={onMenuClick}
        leftIcon={ resource.icon ? <resource.icon /> : <DefaultIcon /> }
      />
    ))}
  </div>
: null
}

//Used with CustomMenu
const mapStateToProps = state => ({
  isLoggedIn: state.admin.auth.isLoggedIn
})

Other information:
Checking the saga responsible for authentication the on case USER_CHECK it is only checked if the user is authenticated with authProvider, if promise resolves no state is changed. If an action to make isLoggedIn resolves the issue, I've created a custom saga that does that, but i think this behaviour should be in RA. This happens because state is cleared when page refreshes and USER_LOGIN_SUCCESS is only called when a logIn occurs and USER_CHECK only does something if promise fails. Instead of using USER_LOGIN_SUCCESS there's also a USER_CHECK_SUCCESS that can be used if check resolves making user loggedIn.

Environment

  • React-admin version: 2.0.0
  • React version: 16.3.2
  • Browser: Any

Most helpful comment

My problem was trusting the isLoggedIn to inform me if a user was logged or not. After refresh, isLoggedIn could not update making my app be in a wrong state. Because I have custom pages that are always accessible, and resources that are only accessible if user is logged, parts of the program were reading isLoggedIn and other the result of calling dataProvider with AUTH_CHECK providing different results. <Authenticated> doesn't solves my problem too because it auto redirects to LogIn page and I don't want that in some cases, a stackoverflow question will be open with that problem since is not a possible bug anymore.

I misinterpreted what a hard refresh should do, I was thinking it should reset all app state making it look like it was the first time user visited the page. And for that reason AUTH_LOGOUT should be called to ensure session would be in initial state. Since I was not sure if that was possible before page refresh, in case it wasn't, it needed to be done on app initiation.

There are some other problems regarding authenticated state after refresh that seem to happen but I don't know if it's something I'm doing wrong or there are indeed problems, if proven to be bug new issues will be open, but more research is needed. Anyway thanks for the help, and sorry to misleading you with this false bug.

All 5 comments

This is a feature request, not a bug. And react-admin won't implement this in core, because a hard "refresh" usually serves as a "reset".

I believe you can do it in userland by adding a custom redux middleware (redux-persist or redux-localstorage). Feel free to reopen if something blocks you from doing so in the react-admin core.

I used another solution to solve the problem. But I still think there's a bug in the framework.

If isLoggedIn state variable indicates if user is logged or not, and calling dataProvider with AUTH_CHECK checks if user session is still active, is possible for the two give contradictory results. In other words is possible for isLoggedIn be false and AUTO_CHECK resolves meaning user is logged.

In a practical example: if our Menu shows some Resources based on user being loggedIn, we can have access to that resources even if they don't appear in the Menu, because authentication will resolve. But if we can access them, why do they not show up?

I don't know what logic do you want to the framework, but from your previous message if refreshing the page resets the whole app, AUTH_LOGOUT should be called before refresh in order to fully reset all the app. Before refreshing or on <Admin/> init, don't know if is possible to logout before page refresh.

isLoggedIn stores the result of the latest AUTH_CHECK call - which is asynchronous. If you want to be sure to get the up-to-date logged in status, don't read isLoggedIn, but use the <Authenticated> component.

I disagree that AUTH_LOGOUT should be called when I hard refresh the app. I don't understand the rationale for that.

Before refreshing or on init, don't know if is possible to logout before page refresh.

I don't understand this sentence.

My problem was trusting the isLoggedIn to inform me if a user was logged or not. After refresh, isLoggedIn could not update making my app be in a wrong state. Because I have custom pages that are always accessible, and resources that are only accessible if user is logged, parts of the program were reading isLoggedIn and other the result of calling dataProvider with AUTH_CHECK providing different results. <Authenticated> doesn't solves my problem too because it auto redirects to LogIn page and I don't want that in some cases, a stackoverflow question will be open with that problem since is not a possible bug anymore.

I misinterpreted what a hard refresh should do, I was thinking it should reset all app state making it look like it was the first time user visited the page. And for that reason AUTH_LOGOUT should be called to ensure session would be in initial state. Since I was not sure if that was possible before page refresh, in case it wasn't, it needed to be done on app initiation.

There are some other problems regarding authenticated state after refresh that seem to happen but I don't know if it's something I'm doing wrong or there are indeed problems, if proven to be bug new issues will be open, but more research is needed. Anyway thanks for the help, and sorry to misleading you with this false bug.

@fzaninotto the problem is that admin often is a fully private app and clients don't want anyone to see its internal structure, for example a menu

Screen Shot 2019-06-12 at 3 38 59 PM

Wrapping the whole app in Authenticated helps, but it duplicates AUTH_CHECK requests for every resource every time you open it.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

9747749366 picture 9747749366  路  3Comments

Dragomir-Ivanov picture Dragomir-Ivanov  路  3Comments

alukito picture alukito  路  3Comments

kdabir picture kdabir  路  3Comments

pixelscripter picture pixelscripter  路  3Comments