MSAL Basics – A Guide to Azure AD’s Authentication Library 5/5 (2)

0

Background

If you have ever created applications that incorporate the Graph API or any other modern authentication-requiring Microsoft API, then you would have most probably worked with ADAL (The Azure Active Directory Authentication Library) to get tokens for API access. The term ADAL has also been affiliated with several Microsoft client applications such as Outlook.

In essence, ADAL has been the basis of connecting to O365 services and APIs. Now, with Azure Active Directory’s new V2.0 endpoint (discussed further in my previous blog: An O365 API Authentication Documentation Guide – The first step in building your Microsoft Graph application), a new library has been introduced; this library is the Microsoft Authentication Library, or MSAL for short.

The purpose of this article is to collate and arrange the basics of this library and incorporate C# examples, when possible. The base concepts of this library should be applicable across all programming languages.

Application Types

As briefly discussed in my previous article, Azure AD App Registrations can span different types of applications; however, these several types can be mainly broken down into two categories:

  • Native (Public Client): This application type is suitable for desktop and mobile applications which cannot safely store client secrets. Respectively, this application registration type does not need a client secret to obtain a token.
  • Web: This application type is suitable for web applications and daemon (user-less) applications. This application registration type requires a client secret to be assigned.

When creating an App Registration instance, you can define your application’s type through its Redirect URI type:

Now, you may ask: why are we discussing application types and not the MSAL library? The answer to this question is fairly simple: MSAL avails two base interfaces which are IPublicClientApplication and IConfidentialClientApplication. These interfaces resemble Native app registrations and Web app registrations, respectively.

IConfidentialClientApplication

Client Credentials Flow

Confidential clients are most widely used in daemon scenarios that do not require user interaction. For such a scenario to work, a token needs to be obtained using the client’s application credentials (client ID and client secret). The MSAL library enables this flow by exposing the “AcquireTokenForClient(scopes)” method. All you need to do is initialize the Confidential Client with a client ID, client secret and redirectURI and then use the aforementioned method with the respective scopes and authority URL. The following C# example summarizes this process:

using System;
using System.Threading.Tasks;
using Microsoft.Identity.Client;


namespace MSAL_ConfidentialClientApp
{
    class Program
    {
        static void Main(string[] args)
        {

            //Declaring the Confidential Client properties

            string ClientID = {Your app registration's client ID};
            string Secret = {Your app registration's client secret};
            string tenantID = {Your tenant ID or .onmicrosoft.com domain};

            //In this example, I am attempting to access the Graph API
            string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
            string url = String.Format("https://login.microsoftonline.com/{0}/oauth2/v2.0/token", tenantID);
            string redirectURI = {Your app registration's redirectURI};


            //Instantiating and adding properties to Confidential Client

            IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(ClientID).WithClientSecret(Secret).WithRedirectUri(redirectURI).Build();

            //Acquiring token using Client Credentials

            Task tokenTask = app.AcquireTokenForClient(scopes).WithAuthority(url, true).ExecuteAsync();
            tokenTask.Wait();

            //Token can be found in tokenTask.Result.AccessToken
        }
    }
}

Interactive Log-in Flow for Web Apps (with Client Secret)

This flow requires an interactive log-in from the user and following the steps of the Authorization Code flow. For a Confidential client, MSAL exposes two methods that can assist in following this flow. An example of implementing the flow is summarized by the following steps:

  • Build the Authorization code URL. MSAL exposes a method to do so: “GetAuthorizationRequestUrl(scopes)”. A C# example on doing so:
//Where app is the same object defined in the previous example
var authCodeURL = app.GetAuthorizationRequestUrl(scopes).WithAuthority(url,true).ExecuteAsync();
authCodeURL.Wait()
  • Have your Web App redirect / reach authCodeURL.Result.AbsoluteURI. This way the user will be prompted to select an account and log-in. After a successful log-in, the page will automatically be redirected to your app’s redirectURI with the Authorization code. Example redirect from my application which has a redirectURI of “https://localhost”: “https://localhost/?code=OAQABAAIAAAAP0w….&session_state=….”. Ideally, your redirectURI needs to be set to a URL that triggers your application into storing this code.
  • Finally, to get a token, you can use MSAL’s “AcquireTokenByAuthorizationCode(scopes, authorizationCode)” method to obtain a token using the code that you stored from the previous step.

IPublicClientApplication

Interactive Log-in Flow for Native Apps

The way in which this flow differs from the Web App’s flow is that MSAL exposes a single method for the entirety of the flow. The “AcquireTokenInteractive(scopes)” method prompts the user to enter his/her credentials and proceeds to obtain a token implicitly. The following C# code snippet is an example on using this method (you can note how this application type does not require a client secret when building it):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Identity.Client;


namespace MSAL_PublicClientApp{
    class Program
    {
        static void Main(string[] args)
        {

        //Declaring the Public Client properties
        string ClientID = {Your app registration's client ID};
        string tenantID = {Your tenant ID or .onmicrosoft.com domain};
        
        //For this example, the API to be accessed is EWS
        string[] scopes = new string[] {"https://outlook.office365.com/.default"};
        string url = String.Format("https://login.microsoftonline.com/{0}/oauth2/v2.0/token", tenantID);
        string redirectURI = {Your app registration's redirectURI};
    
        //Instantiating and adding properties to Public Client
        IPublicClientApplication app = PublicClientApplicationBuilder.Create(ClientID).WithRedirectUri(redirectURI).Build();

        //Acquiring token through user interaction​​
        Task<AuthenticationResult> tokenTask = app.AcquireTokenInteractive(scopes).WithAuthority(url,true).ExecuteAsync();
            tokenTask.Wait();
        }
    }
}

Non-Interactive Log-in Flow

This flow uses OAuth2.0’s ROPC flow which I had discussed in my previous article. Microsoft’s statement on this is that this flow should only be used as a last resort given that it can be the least secure flow (having your application ask for the user’s password is not secure). In summary, all you need to do in addition to the previous sample is to define the username as a string, the password as a SecureString, and use the following method: “AcquireTokenByUsernamePassword(scopes,username,password)”.

More Information

In this article, I have tried my best to summarize and collate the most commonly used flows’ MSAL integrations. For more information regarding other possible flows, I suggest going through the official documentation on the two client interfaces:

I hope that you enjoyed reading this article. I appreciate any feedback and please feel free to leave any questions in the comments section.

0

Please rate this

Leave a Reply

Your email address will not be published. Required fields are marked *