Microsoft-authentication-library-for-js: Avoid overwriting window.msal to support multiple providers for Azure B2C

Created on 23 Jun 2017  路  6Comments  路  Source: AzureAD/microsoft-authentication-library-for-js

I've just got Msal for JS working in an angular application but I had a problem supporting multiple login types for an Azure B2C scenario.

I was doing (for a quick proto)
environment.authSettings.forEach(setting => { //setup new msal and store in array });

I basically had something like
[{policyName: 'b2c_1_facebook',...}, {policyName: 'b2c_1_linkedin',...}, ...]

So that I could have a login(policy) function that picked the appropriate policy and logged in. What the problem is is that as a part of constructing the object, the current best practice is to grab window.msal as the current UserAgentApplication in the tokenRecievedCallback.

UserAgentApplication.ts sets
window.msal = this;

which was causing me to use the facebook agent app for my linkedin agent app.

Can you look at one of these options:

  1. Making window.msal either an array of UserAgentApplications or a dictionary based on the policy name. I understand that this would be a breaking change but it would much more easily support Azure B2C.

  2. Altering tokenRecievedCallback to pass in the userAgentApplication so that we can call the acquire methods on that argument.

Alternatively, if I'm completely missing something obvious that would let me pick out the right application after instantiating an array of them, do let me know. I currently have a hacky workaround that can complete this but this seems like a problem the greater community might want fixed.

If I'm not being clear, I can make a small repo to show what I'm trying to accomplish.

Thanks!

enhancement

Most helpful comment

Hey just a note this is not fixed if you only pass the msal object back in the callback. The iframe generated to acquire a token silently will fail because it relies on the parent Windows msal object, and if you have multiple instances the token acquiring will not work because it tries to verify that the response matches your msal ID. This took forever to debut and fix; I can post a summary sometime soon to show which code points cause issues.

The long and short of it is that the msal object being tied to the window causes problems that we have to dance around.

All 6 comments

Thanks @Wozbo. I believe this makes sense. We'll consider it for the backlog

@Wozbo Can you try out my branch https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/rohitnarula7176/Issue_82 and let me know if it fixes the issue. With this change you can use 'this' inside the tokenRecievedCallback function to refer to the instance of the userAgentApplication as shown below:

var userAgentApplication = new Msal.UserAgentApplication(applicationConfig.clientID, null, authCallback);
        function authCallback(errorDesc, token, error, tokenType) {
            //This function is called after loginRedirect. Inside the function, this will refer to the userAgentApplication instance.
            if (token) {
                this.acquireTokenSilent(applicationConfig.graphScopes).then(function (accessToken) {
                    // Change button to Sign Out
                    updateUI();
                }, function (error) {
                    console.log(error);
                    this.acquireTokenPopup(applicationConfig.graphScopes).then(function (accessToken) {
                        updateUI();
                    }, function (error) {
                        console.log(error);
                    });
                });
            }
            else if (errorDesc || error) {
                console.log(error + ':' + errorDesc);
            }
        }

Hey, this looks pretty good! With this, is there any need for the window.msal object? Seems like a potential artifact that could be removed to not cause confusion.

Hey, I spoke too soon; this fails in an angular service because of the usage of 'this.' Is there any other solution that would be better and backward compatible?

@Wozbo This is now fixed in dev. I have changed the code in a way that you do not need to rely on the window.msal object in the call back function passed in the constructor. You can just create an instance of userAgentApplication and use that instance in the authCallback. With this fix you can still use this.msal in the callback function as before and also use userAgentApplication instance to support multiple login types making it backwards compatible.

 var userAgentApplication = new Msal.UserAgentApplication(applicationConfig.clientID, null, authCallback, { cacheLocation: 'localStorage' });// cacheLocation defaults to sessionStorage if not set in the constructor
        function authCallback(errorDesc, token, error, tokenType) {
            //This function is called after loginRedirect. 
            if (token) {

            }
            else if (errorDesc || error) {
                console.log(error + ':' + errorDesc);
            }
        }

Hey just a note this is not fixed if you only pass the msal object back in the callback. The iframe generated to acquire a token silently will fail because it relies on the parent Windows msal object, and if you have multiple instances the token acquiring will not work because it tries to verify that the response matches your msal ID. This took forever to debut and fix; I can post a summary sometime soon to show which code points cause issues.

The long and short of it is that the msal object being tied to the window causes problems that we have to dance around.

Was this page helpful?
0 / 5 - 0 ratings