Skip to content
This repository has been archived by the owner on Jun 26, 2021. It is now read-only.

Adal.js issues on multiple tabs on a browser #639

Closed
pratap284 opened this issue Oct 9, 2017 · 4 comments
Closed

Adal.js issues on multiple tabs on a browser #639

pratap284 opened this issue Oct 9, 2017 · 4 comments
Assignees
Milestone

Comments

@pratap284
Copy link

If you look at the login function in adal.js, you see the following:

AuthenticationContext.prototype.login = function (loginStartPage) {
    // Token is not present and user needs to login
    if (this._loginInProgress) {
        this.info("Login in progress");
        return;
    }
    var expectedState = this._guid();
    this.config.state = expectedState;
    this._idTokenNonce = this._guid();
    this.verbose('Expected state: ' + expectedState + ' startPage:' + window.location.href);
    this._saveItem(this.CONSTANTS.STORAGE.LOGIN_REQUEST, loginStartPage || window.location.href);
    this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, '');
    this._saveItem(this.CONSTANTS.STORAGE.STATE_LOGIN, expectedState);
    this._saveItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN, this._idTokenNonce);
    this._saveItem(this.CONSTANTS.STORAGE.ERROR, '');
    this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, '');
    var urlNavigate = this._getNavigateUrl('id_token', null) + '&nonce=' + encodeURIComponent(this._idTokenNonce);
    this._loginInProgress = true;
    if (this.config.displayCall) {
        // User defined way of handling the navigation
        this.config.displayCall(urlNavigate);
    }
    else if (this.popUp) {
        this._loginPopup(urlNavigate);
    }
    else {
        this.promptUser(urlNavigate);
    }
};

When this function is called, the expectedState is set to a new GUID and then stored in localStorage before navigating to the Microsoft login page.
When the Microsoft login pages finish what they are doing, navigation returns to our login page where we detect that it is a callback using AuthenticationContext.isCallback(hash) and then get the request info from the hash by calling AuthenticationContext.getRequestInfo(hash).
In that function, it gets the original state value from the hash and compares it to the value that is stored in localStorage. If it is a match, then it proceeds to give the rest of the information needed.

The problem occurs when we have two or mode tabs opened to our application. Our application tries to auto-refresh the token before it expires. If it is unable to do so silently, it navigates to the login page interactively which usually automatically logs them back in and returns to the target page with no user interaction required. If both tabs do this at the same time, however, the first tab initiates the adal login which creates the state GUID and stored it in local storage. Then, before it has a chance to return with the callback hash, the second tab also calls adal login which creates a new Guid and stores it in local storage. Then the first tab comes back with the response, compares the state from the hash to the state in storage, sees that they don’t match and fails to complete the login (and in our code initiates a new login attempt, created yet another state GUID). Then the second tab returns and checks it’s state against localStorage and finds a mismatch and therefore fails to complete the login and initiates a new login attempt. Then the first tab comes back, fails to complete the login, etc. etc. Both tabs are sent into endless login loops because each of them are messing up each other’s login attempts.

@rohitnarula7176
Copy link
Contributor

rohitnarula7176 commented Oct 20, 2017

@pratap284 Thank you for pointing out this issue. This is known limitation of the library in multiple tabs when you use localStorage. You should not face these issues if you set cacheLocation to 'sessionStorage' as session storage is not shared between multiple tabs. Can you confirm if this is the case. We are working on making this work in localStorage.

@rohitnarula7176
Copy link
Contributor

rohitnarula7176 commented Nov 7, 2017

@pratap284 I have fixed this issue in the dev branch. Can you please check to see if this resolves your issue. We will add this fix to our next release.

@pratap284
Copy link
Author

pratap284 commented Nov 8, 2017 via email

@srujankk
Copy link

@pratap284 : Did this solve your issue?
@rohitnarula7176 : I am using 1.0.17. However I am seeing the issue when I open app with different querystring in multiple tabs. The localStorage[LOGIN_REQUEST] gets overwritten by the last tab (querystring values).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants