Oidc-client-js: SigninPopup not working

Created on 3 Sep 2019  路  5Comments  路  Source: IdentityModel/oidc-client-js

Hi,

I'm trying to do the following:

  • Doing the usual user login via SigninRedirect.
  • In case the user logged out of the IDP, I want to have a SigninPopup (to keep the website state).

The first point works great.
The second point fails:

  • After successfull login, the Popup doesn't close.
  • The parent window doesnt get notified about the new accesstoken.

Is there a way to fix that?
Am I doing something stupid here?

This is (part of) my code:

class AuthProvider {
  constructor (managerSettings = {}) {
    this.userManager = new UserManager(managerSettings)
    this.userManager.events.addUserSignedOut(() => this.handleExternalLogout())
    this.userManager.events.addAccessTokenExpired(() => this.handleExternalLogout())
  }

  handleExternalLogout = () => {
    this.userManager.removeUser()
    toastr.warning( undefined, {
                                  timeOut: 0,
                                  showCloseButton: true,
                                  onCloseButtonClick: () => this.signinPopup(),
                                  onToastrClick: () => this.signinPopup()
                                } )
  }

  signinPopup = () => {
    this.userManager.signinPopup()
      .catch(error => console.log('Signin via Popup failed:' + error))
  }

  handlePopupCallback = () => {
    return this.userManager.signinPopupCallback()
      .catch(error => console.log('Popup callback failed:' + error))
  }
}

const authProvider = new AuthProvider({
  popup_redirect_uri: REDIRECT_URI + '/popup-callback.html',
})

export default authProvider

The popup-callback.html is connected to a popup-callback.js via html-webpack-plugin.
The popup-callback.js looks like this:

import authProvider from './authProvider'

authProvider.handlePopupCallback()
bug

Most helpful comment

Ok, so I figured out a dirty workaround.

I changed my code to:

handlePopupCallback = () => {
    return this.userManager.signinPopupCallback(window.location.href.split('?')[1])
      .catch(error => console.log('Popup callback failed:' + error))
  }

This works for me for now.

I would still appreciate, if this could be fixed properly :)

All 5 comments

So, I did a bit of further investigation and it seems to be a bug...

The UrlUtility.parseUrlFragment() produces a weird result that looks the following:
grafik

This in turn results in PopupWindow.notifyOpener() to end in
Log.warn("PopupWindow.notifyOpener: no state found in response url");

Ok, so I figured out a dirty workaround.

I changed my code to:

handlePopupCallback = () => {
    return this.userManager.signinPopupCallback(window.location.href.split('?')[1])
      .catch(error => console.log('Popup callback failed:' + error))
  }

This works for me for now.

I would still appreciate, if this could be fixed properly :)

I can confirm this behaviour. It is a bug.
The underlying problem is around PopupWindow.js:112.
The code falls back to window.location.href, but the delimiter is not set, because UserManager.js:409 does not set it on the PopupNavigator.

One idea to fix this could be to modify the regex in UrlUtility.js:43 to also exclude # and ? on the first part.

Btw. I try to use the standard Browser API to deal with this, so as a hack I'm actually doing this right now:

handlePopupCallback = () => {
    return this.userManager.signinPopupCallback((new URLSearchParams(location.search)).toString())
      .catch(error => console.log('Popup callback failed:' + error))
  }

Thank you guys, you helped me out very quickly.
I would be very happy, if this could be solved some day :)

Any news on this?

Was this page helpful?
0 / 5 - 0 ratings