Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 45

MSAL in .NET: User Sign-in Implementation

Recommended resources

Hello! Welcome back to our course on becoming an Azure Developer.

In our last lesson, you successfully registered a client web application and a back-end API in Microsoft Entra ID. You configured the necessary application IDs, a client secret, and the API permissions, establishing the foundational trust relationship between your apps and the Microsoft Identity Platform.

Today, we will bring those configurations to life. Our goal is to achieve the learning outcome: Implement user sign-in using the Microsoft Authentication Library (MSAL) in a .NET application. We'll take the configuration values from the previous lesson and integrate them into a .NET web application to create a fully functional and secure user sign-in and sign-out experience.

MSAL and Microsoft.Identity.Web: Choosing the Right Tool

The learning outcome mentions the Microsoft Authentication Library (MSAL), which is the core library for interacting with the Microsoft Identity Platform. However, for building ASP.NET Core applications (web apps and web APIs), Microsoft provides a higher-level library called Microsoft.Identity.Web. It sits on top of MSAL.NET and is specifically designed to simplify integration with the ASP.NET Core framework, handling much of the boilerplate code for you.

The following flowchart illustrates when to use each library. As you can see, for an ASP.NET Core web app, Microsoft.Identity.Web is the recommended path.

Microsoft Identity Web and MSAL.NET Decision Flowchart
This flowchart from Microsoft shows the decision process for choosing between MSAL.NET and Microsoft.Identity.Web. For ASP.NET Core web apps, Microsoft.Identity.Web is the recommended library.

Throughout this lesson, we will use Microsoft.Identity.Web because it is the current best practice for this scenario and what you'll most likely encounter on the AZ-204 exam.


The Authentication Flow in a Web App

Web applications use a redirection-based flow called the Authorization Code Flow to sign in users. Understanding this flow is key to knowing what Microsoft.Identity.Web does for you under the scenes.

Web Application User Sign-in Flow with Microsoft Entra ID
This sequence diagram illustrates the authorization code flow. The user's browser is redirected between the Web App and Microsoft Entra ID to securely handle authentication and token issuance.

Here's a breakdown of the steps shown in the diagram:

  1. A user navigates to your web app.
  2. The app detects the user is not authenticated and redirects them to the Microsoft Entra ID sign-in page.
  3. The user enters their credentials, performs multi-factor authentication if required, and consents to the permissions your app requested.
  4. After a successful sign-in, Entra ID redirects the user back to your app's pre-configured Redirect URI. This redirect includes a temporary authorization code.
  5. Your web app's back end receives this code and makes a secure, direct call to Entra ID, exchanging the code (and its client secret) for an ID token and an access token.
  6. The app validates the ID token to confirm the user's identity and creates a session cookie to keep the user signed in.

Now, let's implement this flow in code.


1. Project Setup and Configuration

First, you'll need a new ASP.NET Core web application project. We'll then configure it with the values from your app registration.

  1. Create a Project: Open Visual Studio or use the .NET CLI to create a new ASP.NET Core Web App (Model-View-Controller) project.

  2. Add NuGet Packages: Install the necessary Microsoft.Identity.Web packages. Open the terminal in your project directory and run:

    dotnet add package Microsoft.Identity.Web
    dotnet add package Microsoft.Identity.Web.UI
    
  3. Configure appsettings.json: Open the appsettings.json file. Add an AzureAd section and populate it with the details from the client web application (GameStore.Frontend or similar) you registered in the previous lesson.

    {
      "AzureAd": {
        "Instance": "https://login.microsoftonline.com/",
        "Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]",
        "TenantId": "[Enter your Tenant ID]",
        "ClientId": "[Enter your Client ID]",
        "CallbackPath": "/signin-oidc",
        "SignedOutCallbackPath": "/signout-callback-oidc",
        "ClientSecret": "[Enter your Client Secret]"
      },
      "Logging": { ... },
      "AllowedHosts": "*"
    }
    

    You can find your Tenant ID and Client ID on the overview page of your app registration in the Entra admin center.

A Critical Note on Secrets

Pasting a client secret directly into appsettings.json is a security risk, as this file is often committed to source control. For local development, you should use the .NET Secret Manager.

To do this:

  1. Initialize the secret manager in your project's directory:
    dotnet user-secrets init
    
  2. Add your client secret to the secret store. The key AzureAd:ClientSecret directly maps to the JSON structure.
    dotnet user-secrets set "AzureAd:ClientSecret" "PASTE_YOUR_CLIENT_SECRET_VALUE_HERE"
    
  3. Remove the ClientSecret line from appsettings.json. The configuration system will automatically pick it up from the secret store during development.

2. Integrating Authentication into Your Application

With the configuration in place, you only need to add a few lines to your Program.cs file to enable authentication.

Tutorial: Configure an ASP.NET Core web app for authorization

The official Microsoft documentation provides the exact code needed to enable authentication services and middleware. We will use the snippets from this tutorial.

Read through the sections 'Add authorization to HomeController.cs' and 'Add authentication and authorization elements to Program.cs'. Focus on understanding the purpose of the AddMicrosoftIdentityWebApp and AddMicrosoftIdentityUI methods, as well as the UseAuthentication and UseAuthorization middleware.

Based on the documentation, make the following changes to your Program.cs:

  1. Add using statements at the top:

    using Microsoft.AspNetCore.Authentication.OpenIdConnect;
    using Microsoft.Identity.Web;
    using Microsoft.Identity.Web.UI;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc.Authorization;
    
  2. Add the authentication services after builder.Services.AddControllersWithViews();:

    // Add services for authentication with the Microsoft identity platform
    builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
    
    builder.Services.AddControllersWithViews(options =>
    {
        var policy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
        options.Filters.Add(new AuthorizeFilter(policy));
    }).AddMicrosoftIdentityUI();
    
    • AddMicrosoftIdentityWebApp reads your AzureAd configuration and sets up all the OIDC parameters for the Authorization Code Flow.
    • AddMicrosoftIdentityUI adds the default user interface for sign-in, sign-out, and other account management actions.
    • The AuthorizeFilter ensures that all pages in your application will require authentication by default.
  3. Add the middleware to the request processing pipeline. Place these lines after app.UseRouting(); and before app.MapControllerRoute(...):

    app.UseAuthentication();
    app.UseAuthorization();
    

    The order is important! UseAuthentication must come before UseAuthorization.


3. Adding the Sign-in/Sign-out UI

Now, let's add the UI elements to your application's layout so the user can sign in and see their status.

  1. Create a new file in the Views/Shared folder named _LoginPartial.cshtml.

  2. Add the following Razor code to the file. This code checks if the user is authenticated. If they are, it displays their username and a sign-out link. Otherwise, it shows a sign-in link.

    @using System.Security.Principal
    
    <ul class="navbar-nav">
    @if (User.Identity?.IsAuthenticated == true)
    {
        <li class="nav-item">
            <span class="navbar-text text-dark">Hello @User.Identity?.Name!</span>
        </li>
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignOut">Sign out</a>
        </li>
    }
    else
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignIn">Sign in</a>
        </li>
    }
    </ul>
    

    The asp-area="MicrosoftIdentity" tag helper points to the default UI controllers provided by the Microsoft.Identity.Web.UI package.

  3. Finally, open Views/Shared/_Layout.cshtml and render this new partial view inside the navigation bar. Find the <div> with the navbar-collapse class and add the partial view tag at the end of the <ul>:

    <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
        <ul class="navbar-nav flex-grow-1">
            <li class="nav-item">
                <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
            </li>
            <li class="nav-item">
                <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
            </li>
        </ul>
        <partial name="_LoginPartial" />
    </div>
    

4. Test Your Application

You are now ready to test the entire flow.

  1. Run your application (dotnet run or press F5 in Visual Studio).
  2. Because we added a global AuthorizeFilter, your app should immediately redirect you to the Microsoft sign-in page.
  3. Sign in with a user account from your tenant.
  4. After a successful login, you will be redirected back to your application's home page.
  5. Observe the navigation bar: it should now greet you by name and show a "Sign out" link.
  6. Click "Sign out". You should be logged out of the application and see the "Sign in" link again.

The following video demonstrates a very similar user experience in a Blazor application. Watching this segment can help you visualize the expected outcome.

Securing ASP.NET Core Apps With OIDC and Microsoft Entra ID (Azure AD) – Full Course

The video 'Securing ASP.NET Core Apps With OIDC and Microsoft Entra ID' by Julio Casal shows a complete login and logout flow. Watch this to see the user experience you just built in action.

Watch the video from 00:56:32 to 00:57:38 to see the login process, and then from 01:03:05 to 01:03:41 to see the logout and display of user information.


Conclusion

Congratulations! You have successfully implemented a secure user sign-in flow in a .NET application using the Microsoft Identity Platform. You've gone from theoretical configuration to a working, authenticated application.

Key Takeaways:

  • Microsoft.Identity.Web is the high-level library that simplifies integrating ASP.NET Core applications with Microsoft Entra ID.
  • Application settings are stored in appsettings.json, with secrets protected by the .NET Secret Manager.
  • Authentication is configured in Program.cs by adding services (AddMicrosoftIdentityWebApp) and middleware (UseAuthentication).
  • The [Authorize] attribute is used to protect pages and trigger the authentication flow.
  • The Microsoft.Identity.Web.UI package provides default UI and controllers for a seamless sign-in/sign-out experience.

Next Steps

In our next lesson, we will focus on "Configure API permissions (delegated vs. application) and define scopes for a web API." While you've already touched on this during app registration, we will take a deeper dive into the meaning of different permission types and how they affect what your application is allowed to do after a user has signed in. This is a crucial step before we acquire an access token to call our protected back-end API.