okta-oidc-js
okta-oidc-js copied to clipboard
authState.isPending is true after logout
I'm submitting this issue for the package(s):
- [x] okta-react
I'm submitting a:
- [x] Bug report
Current behavior
authState.isPending is true after calling authService.logout()

This seems wrong to me since it breaks this official example:
const { authState, authService } = useOktaAuth();
if (authState.isPending) {
return <div>Loading...</div>;
}
Expected behavior
All fields of authState are set to null after logout.
Minimal reproduction of the problem with instructions
On https://github.com/okta/samples-js-react (custom-login)
@shuowu: go to login page, then click back button directly without login.
Not the scenario I initially described, but probably has the same root cause (isPending == true when it should not be).
Extra information about the use case/user story you are trying to implement
Essentially, this is what happens: when a user initiates logout, the first authState change the app is receiving looks like the screenshot (all fields are null, isPending is true). After that, most of the time there is another authState update with isPending == false (I don't know what triggers it). But sometimes it does not happen and users observe "Loading..." indefinitely. In any case, I can verify with a debugger that the first update to authState after logout always contains isPending == true which seems to be a bug.
Environment
- Package Version: 3.0.4
- Browser: Chrome 86.0.4240.8
- OS: MacOS Catalina 10.15.6
- Node version (
node -v): v12.18.3
@patkovskyi isPending is set to true (the default state) by design when logout happens, as a success logout will do a hard reload to refresh the memory, then the client will re-evaluate the authState to set isPending to either true or false.
But sometimes it does not happen and users observe "Loading..." indefinitely.
This may be caused by a logout failure, then the authState failed to be updated properly.
I think it would make sense to update authState.error if logout fails.
Internal Ref: OKTA-326953
@shuowu thanks for taking a look!
I find the meaning of isPending quite confusing. My initial expectation was that it means: authentication flow is currently running. But there's no ongoing authentication flow after logout.
I encountered two cases when having isPending set to true by design consistently breaks a React app:
- onbeforeunload event was intercepted and a user chose not to leave the page after authService.logout() was executed. I guess hard reload you're mentioning does not happen in this case.
- when I'm not logged in and navigate via back button to the /login route which contains this code:
const { authState, authService } = useOktaAuth();
if (authState.isPending) {
return <div>Loading...</div>;
}
isPending is true but the authentication process does not trigger so the page just stays in "Loading..."
My initial expectation was that it means: authentication flow is currently running
@patkovskyi - Close, but not quite. isPending means "We are currently figuring out what your authorization is". This can be waiting on an async currently-running authorization flow, but it could also be waiting on an async retrieval of tokens (such as IndexedDB).
Authorization state is decided by checking tokens, tokens MAY be stored in an async way, so knowing if you are authorized is async until it is decided, and until that is decided you are 'pending'.
That's why on initial load, the auth state is pending, and if you aren't authenticated, it will stop being pending and become false - the async token check returned, and you weren't authenticated.
@swiftone thanks for clarification!
So, is there anything I can do to make okta-react figure out the real authentication state after I use back button (more details in my previous message)?
@patkovskyi
onbeforeunload event was intercepted and a user chose not to leave the page after authService.logout() was executed.
The hard reload is not only to clear the memory, but also redirect to logout uri to clear user session from backend, then redirect user back based on the logoutRedirectUrl, which means this process should not be interrupted with onbeforeunload listener.
when I'm not logged in and navigate via back button to the /login route which contains this code
The sdk evaluated the authState based on the tokens state when the route changes in app. So I don't think any action is needed from the app code. Or do you see issues with navigate back by the back button?
@shuowu
When I click Back after a full successful logout, it brings me to /login route where isAuthenticated == false, isPending == true, tokens are undefined and nothing else happens.
Here's a video repro for the Back button issue: https://www.dropbox.com/s/t6xrm5adozxpswp/Screen%20Recording%202020-09-01%20at%2021.00.03.mov I show the whole flow: Login -> Logout -> clicking Back (around 00:55)
@patkovskyi Thanks for the video, I am able to reproduce the issue locally now.
Internal Ref: OKTA-327283
@shuowu
I was unable to reproduce this issue on samples-js-react custom-login, even after I changed okta-react version from 3.0.0 to 3.0.4. I'm curious how you reproduced it, maybe it points to some specific thing in my code that triggers this issue.
Meanwhile, I think I found a dirty workaround: adding authState.isAuthenticated === null condition fixes the problem in my repro video.
const { authState, authService } = useOktaAuth();
if (authState.isPending && authState.isAuthenticated === null) {
return <div>Loading...</div>;
}
return authState.isAuthenticated
? <Redirect to={{ pathname: Routes.root }} />
: <SignInWidget />;
@patkovskyi go to login page, then click back button directly without login.
Having the same issue. Any fixes in the works?
I'm also having this issue. At 3.0.8, isPending is true after having logged out, and stays true. Downgrading to 3.0.0 produces expected results, where isPending is true until isAuthenticated is false.
@sero323 & @lee-bennie: We do not have a solution at this time, but the team is reviewing priorities today and I'll see if we can get this bumped up.
Meanwhile, can you clarify if this is happening every time on logout, most times, or occasionally? (original report was "most of the time it works")
Also, can you detail what steps your app takes on logout to see if anything is different from the other report?
@sero323 & @lee-bennie: We do not have a solution at this time, but the team is reviewing priorities today and I'll see if we can get this bumped up.
Meanwhile, can you clarify if this is happening every time on logout, most times, or occasionally? (original report was "most of the time it works")
Also, can you detail what steps your app takes on logout to see if anything is different from the other report?
In my case I'm really just treating "after logout" as a blank slate, so if my issue doesn't belong here, let me know. But I've narrowed the change down to v3.0.4.
So at <= 3.0.3, when with when I look at the state of Security, I can see:
{ _authState: { isAuthenticated: false, idToken: undefined, accessToken: undefined } }
and then at >= 3.0.4:
{ _authState: { isAuthenticated: false, idToken: undefined, accessToken: undefined, isPending: true } }
These are with clean application storage, so no cookies, no local or session storage. Clean install of node modules.
authParams: { responseType: ['id_token', 'token'], scopes: ['openid', 'email', 'profile'], pkce: true, }
Any progress on this issue?
@sero323 - This should be corrected in okta-react 3.0.9+, see https://github.com/okta/okta-react/releases/tag/okta-react-3.0.9.
Let us know if you continue to see this problem.
@sero323 I can confirm that 3.0.9 fixed it for me.