Can't get token when log in with Azure Active Directory using msal.js

3.2k views Asked by At

I have problem with get token when log in with Azure Active Directory using msal.js.

Maybe I'll describe you how the app works in several situations.

I. Automatic login with Active Directory Authentication is disabled. Callback on Application Registration Portal is set to home page of the app. I used the code from https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/devApps/VanillaJSTestApp/index_LoginPopup.html

  1. Enter the app without authorization
  2. Click on button which runs loginPopup, after log in get token.

Everything works, but I want authorization with Active Directory Authentication

II. Automatic login with Active Directory Authentication is enabled. Callback on Application Registration Portal is set to "***.auth/login/aad/callback". I used the code from https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/devApps/VanillaJSTestApp/index_LoginPopup.html

  1. Enter the app with authorization and log in with Active Directory Authentication
  2. acquireTokenSilent is sending error like "user_login_error:User login is required".
  3. Click on button which runs loginPopup, after log in I get error like "The reply address **** does not match the reply addresses configured for the application"

UPDATE: After set userAgentApplication.redirectUri = '****/.auth/login/aad/callback' and run loginPopup, token is delivered, but it's still double log in.

To summarize, after login with Azure I get error from acquireTokenSilent "user_login_error:User login is required".

III. I would like the app to behave as follows:

  1. Enter the app with authorization and log in with Active Directory Authentication
  2. Get token

Can I do it like this?

2

There are 2 answers

0
Andre Teixeira On

If you want to authenticate the user by the client using msal.js and also protect your Web API, then disable the 'App Service Authentication' in Azure. Protect your Web API using OWIN middleware instead.

This following sample shows a Web API protected by Azure AD Endpoint V2 using msal.js: https://github.com/Azure-Samples/active-directory-javascript-singlepageapp-dotnet-webapi-v2

0
Fei Xue On

You were mixing the Easy Auth and protecting the site manually using MSAL.

If you want the popup page for login with Azure Active Directory popup automatically, you can modify the source to add the function to execute the loginPopup() method when the document is loaded completely. Here is an code sample for your reference:

<html>
<head>
    <title>authentication with Msal.js app</title>
    <style>
        .hidden {
            visibility: hidden
        }

        .visible {
            visibility: visible
        }
    </style>
</head>
<body>
    <!-- bluebird only needed if this page needs to run on Internet Explorer -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js" class="pre"></script> 
    <script src="https://secure.aadcdn.microsoftonline-p.com/lib/0.1.1/js/msal.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js" class="pre"></script>

    <h1>Sending an email with msal.js and Microsoft Graph</h1>
    <div>
        <div id="label">Sign-in with Microsoft</div>
        <button id="auth" onclick="loginPopup();">Login (with Popup)</button>
    </div>
    <div id="sendEmail" class="hidden">
        <input id="emailToSendTo" type="text" />
        <button id="auth" onclick="sendEmail();">Send email</button>
    </div>

    <pre class="response"></pre>

    <script class="pre">
        var applicationConfig = {
            clientID: '1e6af2ed-686c-4914-96ed-0cd7b1673cbb',
            graphEndpoint: "https://graph.microsoft.com/v1.0/me/sendMail",
            graphScopes: ["user.read", "mail.send"]
        };
    </script>

    <script>
        var userAgentApplication = new Msal.UserAgentApplication(applicationConfig.clientID, applicationConfig.authority, authCallback);
        function authCallback(errorDesc, token, error, tokenType) {
            //This function is called after loginRedirect. msal object is bound to the window object after the constructor is called.
            if (token) {
            }
            else {
                log(error + ":" + errorDesc);
            }
        }

        function loginPopup() {
            userAgentApplication.loginPopup(applicationConfig.graphScopes).then(function (idToken) {
                //Login Success
                userAgentApplication.acquireTokenSilent(applicationConfig.graphScopes).then(function (accessToken) {
                    //AcquireToken Success
                    updateUI();
                }, function (error) {
                    //AcquireToken Failure, send an interactive request.
                    userAgentApplication.acquireTokenPopup(applicationConfig.graphScopes).then(function (accessToken) {
                        updateUI();
                    }, function (error) {
                        console.log(error);
                    });
                })
            }, function (error) {
                console.log(error);
            });

        }

        function updateUI() {
            var authButton = document.getElementById('auth');
            authButton.innerHTML = 'logout';
            authButton.setAttribute('onclick', 'logout();');
            var label = document.getElementById('label');
            label.innerText = "Hello " + userAgentApplication.getUser().name + "! Please send an email with Microsoft Graph";

            // Show the email address part
            var sendEmailSpan = document.getElementById('sendEmail');
            sendEmailSpan.className = "visible";
            var emailAddress = document.getElementById('emailToSendTo');
            emailAddress.value = userAgentApplication.getUser().displayableId;
        }

        function logout() {
            // Removes all sessions, need to call AAD endpoint to do full logout
            userAgentApplication.logout();
        }

        function sendEmail() {
            userAgentApplication.acquireTokenSilent(applicationConfig.graphScopes)
                .then(function (token, error) {
                    $.ajax({
                        type: "POST",
                        contentType: "application/json",
                        dataType: 'json',
                        beforeSend: function (request) {
                            request.setRequestHeader('Authorization', 'bearer ' + token);
                        },
                        url: applicationConfig.graphEndpoint,
                        data: JSON.stringify({ 'message': getEmail(), 'saveToSentItems': true }),
                        processData: false,
                        success: function (msg) {
                            log('Mail sucessfully sent.');
                        },
                        statusCode: {
                            200: function () {
                                log('Mail sucessfully sent.');
                            },
                            202: function () {
                                log('Mail sucessfully sent.');
                            }

                        }
                    });
                });
        }

        function log(s) {
            document.body.querySelector('.response').appendChild(document.createTextNode("\n\n" + JSON.stringify(s, true, 2)));
        }

        function getEmail() {
            var email = {
                Subject: 'Welcome to Microsoft Graph development with Msal and the Microsoft Graph sample',
                Body: {
                    ContentType: 'HTML',
                    Content: getEmailContent()
                },
                ToRecipients: [
                    {
                        EmailAddress: {
                            Address: userAgentApplication.getUser().displayableId
                        }
                    }
                ]
            };
            return email;
        }

        // Get the HTMl for the email to send.
        function getEmailContent() {
            return "<html><head> <meta http-equiv=\'Content-Type\' content=\'text/html; charset=us-ascii\'> <title></title> </head><body style=\'font-family:calibri\'> <p>Congratulations " + userAgentApplication.getUser().name + ",</p> <p>This is a message from the Microsoft Graph Connect sample. You are well on your way to incorporating Microsoft Graph endpoints in your apps. </p> <h3>What&#8217;s next?</h3><ul><li>Check out <a href='https://graph.microsoft.io' target='_blank'>graph.microsoft.io</a> to start building Microsoft Graph apps today with all the latest tools, templates, and guidance to get started quickly.</li><li>Use the <a href='https://graph.microsoft.io/graph-explorer' target='_blank'>Graph explorer</a> to explore the rest of the APIs and start your testing.</li><li>Browse other <a href='https://github.com/microsoftgraph/' target='_blank'>samples on GitHub</a> to see more of the APIs in action.</li></ul> <h3>Give us feedback</h3> <ul><li>If you have any trouble running this sample, please <a href='https://github.com/microsoftgraph/angular-connect-rest-sample/issues' target='_blank'>log an issue</a>.</li><li>For general questions about the Microsoft Graph API, post to <a href='https://stackoverflow.com/questions/tagged/microsoftgraph?sort=newest' target='blank'>Stack Overflow</a>. Make sure that your questions or comments are tagged with [microsoftgraph].</li></ul><p>Thanks and happy coding!<br>Your Microsoft Graph samples development team</p> <div style=\'text-align:center; font-family:calibri\'> <table style=\'width:100%; font-family:calibri\'> <tbody> <tr> <td><a href=\'https://github.com/microsoftgraph/angular-connect-rest-sample\'>See on GitHub</a> </td> <td><a href=\'https://officespdev.uservoice.com/\'>Suggest on UserVoice</a> </td> <td><a href=\'https://twitter.com/share?text=I%20just%20started%20developing%20%23Angular%20apps%20using%20the%20%23MicrosoftGraph%20Connect%20sample!%20&url=https://github.com/microsoftgraph/angular-connect-rest-sample\'>Share on Twitter</a> </td> </tr> </tbody> </table> </div>  </body> </html>";
        };


        $(document).ready(function () {
            loginPopup();
        });
    </script>
</body>
</html>