How should handle users logout use case when multiple browser tabs are opened
Asked Answered
C

4

6

I am using angular-oauth2-oidc with Identity Server 4.

Users need to Login via OpenId Connect Implicit Flow. My Id and Access token are stored in the web browser localStorage.

When user opens multiple browser tabs and then user logs out from one of the tabs, how should I handle rest of the tabs?

I have tried to catch session_terminated events , and they try to log the user out. However, it does not redirect the user back to the login page.

this.oauthService.events.filter(e => e.type ==='session_terminated')
                  .subscribe(e => {this.oauthService.logout();})

any suggestions? thanks

Calica answered 1/8, 2018 at 6:44 Comment(0)
R
2

Interesting. It was on my to do list to see how this works with the library anyways.

I had already created a dedicated playground example repo that was perfect for testing this. What I found was that there are two distinct scenarios:

  1. The user goes to the IdentityServer themselves, and click log out
  2. The user does a Single Sign Out via our own app

Only in the first scenario do you get a session_terminated event. In the second scenario (which you seem to have) you get a session_error event in the second tab because the first tab:

  1. Clears your stored tokens
  2. Redirects you to the log out page (where you still have to click log out)

You can see as much in these screencaptures:

Scenario 1: log out explicitly in a third tab

from-server

Scenario 2: log out from the app

redirection

So I think your solution is to also hook into session_error, or something similar.


Footnote: thinking some more about the above, I reckon that other workarounds might also be possible by listening to localStorage events, and notice when the access_token is being cleared by another tab.

Regalia answered 1/8, 2018 at 10:0 Comment(0)
W
2

I've experienced a similar issue: using angular-oauth2-oidc with default storage (sessionStorage) leads to the behavior that if a user opens a new Tab (Tab B), he is being logged-in again with a new Token. When he logs-out on Tab A, the token stored in sessionStorage of Tab B is still there, of course.

Using localStorage has the disadvantage that the token is persisted even if the browser is closed (kinda "keep me logged in").

What I've done to overcome this is using an own OAuthStorage that internally uses sessionStorage but if the user logs out, it sends an event to all other open Browser-Tabs and triggers a clearing up of the session-storages there.

See the accroding gist

Waylonwayman answered 25/4, 2019 at 8:13 Comment(0)
S
1

This is what the OIDC session management spec is all about. You can be notified on the client side when their IDP session changes/ends and then react accordingly.

http://openid.net/specs/openid-connect-session-1_0.html#ChangeNotification

Works well, doesn't have any network overhead and gives you full control over what to do when the condition is detected.

Seabolt answered 1/8, 2018 at 13:38 Comment(3)
I think though that the event OP mentions (session_terminated) is in fact the library's implementation of that spec. And it does work if you log out straight on the server. The issue (I think) is that the library will clear localStorage/sessionStorage and timers and whatnot already when sending you to the logout uri, and then the session checks in other tabs stop working. The question is (I think) how to solve that with angular-oath2-oidc. But OP might correct me on that.Regalia
In this case a user opens two tabs and logout (this.oauthService.logout()) from one of the tab.Calica
Thank you guys. I have done more investigation based on your comment. This is my use case: A user opens two tabs (TabA and TabB), and logout from one of the TabA.(using this.oauthService.logout() provided by angular-oath2-oidc library) Then, TabB will get a session_terminated event, I ask the user to login from TabB. Basically, I just provided login page linkfor the user to re-login, if session is terminated. In addition, session_error and cleaned localstorage events might need to be handled as well as suggested by @Regalia tCalica
T
0

You can check if access_token is invalid in localstorage or sessionStorage

  @HostListener('window:storage', ['$event'])
  onStorageChange(e) {
    if (e.storageArea === localStorage) {
      else if(e.key === 'access_token' && !e.newValue  && !this.oauthService.hasValidAccessToken()) {
        this.authTokenService.logout();
      }
    }
    
  }
Terrazzo answered 27/5, 2022 at 12:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.