iframe session issue in OIDC client

1.8k views Asked by At

I'm using OIDC Client and WSO2 API Manager 3.2.0 in my angular application for authentication. Everything works fine until I hit log out.

First, I log into the application from one tab and then duplicate that tab after a successful login. After that, when I log out from one tab, other tabs also should be logged out, but it does not happen. I have created an iframe and constantly check the session as below.

.ts file:

  baseUrl = new URL(window.location.href);
  callbackURI = this.baseUrl.origin + '/slate/dashboard';

  checkSessionURL = this.sanitizer.bypassSecurityTrustResourceUrl('https://localhost:9443/oidc/checksession' + '?client_id='
            + localStorage.getItem('client_id') + '&redirect_uri=' + this.callbackURI);

  constructor(private sanitizer: DomSanitizer, private authService: AuthService) {
  }

  ngOnInit(): void {
  }

  ngAfterViewInit(): void {
    if (this.authService.isLoggedUser()) {
      this.checkSession();
    }
  }

  isIFrame = (input: HTMLElement | null): input is HTMLIFrameElement =>
    input !== null && input.tagName === 'IFRAME'

  /**
   * Invoke check session OIDC endpoint.
   */
  checkSession(): void {
    setInterval(() => {
      const msg = localStorage.getItem('client_id') + ' ' + localStorage.getItem('sessionState');
      const frame = document.getElementById('iframeOP');
      if (this.isIFrame(frame) && frame.contentWindow) {
        frame.contentWindow.postMessage(msg, 'https://localhost:9443/oidc/checksession');
      }
    }, 3000);
  }

.HTML file:

<iframe
  title='iframeOP'
  id='iframeOP'
  [src]="checkSessionURL"
></iframe>

After refreshing the duplicate tab, I'm getting this.

https://localhost:9443/authenticationendpoint/oauth2_error.do?oauthErrorCode=access_denied&oauthErrorMsg=Error+occurred+while+extracting+data+from+id+token.

But, the log out in duplicated tabs should happen automatically. I appreciate if anyone could help.

2

There are 2 answers

0
Jan Garaj On BEST ANSWER

You need to share logout event (and invoke logout function) between tabs. Suggested implementation: your SPA (each tab) needs to watch an external-logout boolean setting in local storage, using the browser Storage API (reference). More modern implementation may use Broadcast Channel API to broadcast logout event between tabs.

0
Theviyanthan Krishnamohan On

From the code you have shared, it seems like your single logout logic is incomplete. You have implemented the logic only to post a message to the iframe. However, it would be best if you also listened to the iframe for its response to your message.

You may receive "changed", "unchanged", or "error" as a response. If you receive "error", then you need to sign the user out.

If you get "changed", then you need to send an authorization call within another iframe with an additional query parameter prompt=none.

If you get an authorization code in response, then that means the user is logged in. So, you need to update the session state parameter that you have stored with the one in the response.

If you don't get an authorization code, then that means the user is logged out, so you will have to log the user out.

If the message says "unchanged", then you need not do anything.

To simplify things, you can use our Angular SDK, which takes care of these things for you right out of the box.