Tutorial: Prepare an ASP.NET Core web app for authentication in an external tenant

This tutorial is part 2 of a series that demonstrates how to build an ASP.NET Core web application and prepare it for authentication using the Microsoft Entra admin center. In Part 1 of this series, you registered an application and configured user flows in your external tenant. This tutorial demonstrates how to create an ASP.NET Core web app, and configure it for authentication.

In this tutorial you'll;

  • Create an ASP.NET Core project in Visual Studio Code
  • Add the required NuGet packages
  • Configure the settings for the application
  • Add code to implement authentication

Prerequisites

Create an ASP.NET Core project

  1. Open Visual Studio Code, select File > Open Folder.... Navigate to and select the location in which to create your project.

  2. Open a new terminal by selecting Terminal > New Terminal.

  3. Enter the following command to make a Model View Controller (MVC) ASP.NET Core project.

    dotnet new mvc -n dotnetcore_webapp
    

Install identity packages

Identity related NuGet packages must be installed in the project to authenticate users.

  1. Enter the following commands to change into the dotnetcore_webapp folder and install the relevant NuGet package:

    cd dotnetcore_webapp
    dotnet add package Microsoft.Identity.Web.UI
    

Configure the application for authentication

  1. Open the appsettings.json file and replace the existing code with the following snippet.

    {
      "AzureAd": {
        "Authority": "https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com/",
        "ClientId": "Enter_the_Application_Id_Here",
        "ClientCredentials": [
          {
            "SourceType": "ClientSecret",
            "ClientSecret": "Enter_the_Client_Secret_Here"
          }
        ],
        "CallbackPath": "/signin-oidc",
        "SignedOutCallbackPath": "/signout-callback-oidc"
      },
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*"
    }
    
    • Authority - The identity provider instance and sign-in audience for the app. Replace Enter_the_Tenant_Subdomain_Here with the subdomain of your external tenant. To find this, select Overview in the sidebar menu, then switch to the Overview tab. Find the Primary domain, in the form caseyjensen.onmicrosoft.com. The subdomain is caseyjensen.
    • ClientId - The identifier of the application, also referred to as the client. Replace the text in quotes with the Application (client) ID value that was recorded earlier from the overview page of the registered application.
    • ClientSecret - The value of the client secret you created in Prepare your tenant. Replace the text in quotes with the client secret value in the Microsoft Entra admin center.
    • CallbackPath - Is an identifier to help the server redirect a response to the appropriate application.
  2. Save changes to the file.

  3. Open the Properties/launchSettings.json file.

  4. In the https section of profiles, change the https URL in applicationUrl so that it reads https://localhost:7274. You used this URL to define the Redirect URI.

  5. Save the changes to your file.

Use custom URL domain (Optional)

Use a custom domain to fully brand the authentication URL. From a user perspective, users remain on your domain during the authentication process, rather than being redirected to ciamlogin.com domain name.

Follow these steps to use a custom domain:

  1. Use the steps in Enable custom URL domains for apps in external tenants to enable custom URL domain for your external tenant.

  2. Open appsettings.json file:

    1. Update the value of the Authority property to https://Enter_the_Custom_Domain_Here/Enter_the_Tenant_ID_Here. Replace Enter_the_Custom_Domain_Here with your custom URL domain and Enter_the_Tenant_ID_Here with your tenant ID. If you don't have your tenant ID, learn how to read your tenant details.
    2. Add knownAuthorities property with a value [Enter_the_Custom_Domain_Here].

After you make the changes to your appsettings.json file, if your custom URL domain is login.contoso.com, and your tenant ID is aaaabbbb-0000-cccc-1111-dddd2222eeee, then your file should look similar to the following snippet:

{
  "AzureAd": {
    "Authority": "https://login.contoso.com/aaaabbbb-0000-cccc-1111-dddd2222eeee",
    "ClientId": "Enter_the_Application_Id_Here",
    "ClientCredentials": [
      {
        "SourceType": "ClientSecret",
        "ClientSecret": "Enter_the_Client_Secret_Here"
      }
    ],
    "CallbackPath": "/signin-oidc",
    "SignedOutCallbackPath": "/signout-callback-oidc",
    "KnownAuthorities": ["login.contoso.com"]
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Add authorization to HomeController.cs

The HomeController.cs file contains the code for the home page of the application and needs to have the capability to authorize the user. The Microsoft.AspNetCore.Authorization namespace provides the classes and interfaces to implement authorization to the web app, and the [Authorize] attribute is used to specify that only authenticated users can use the web app.

  1. In your code editor, open Controllers\HomeController.cs file.

  2. Authorization needs to be added to the controller, add Microsoft.AspNetCore.Authorization so that the top of the file is identical to the following snippet:

    using System.Diagnostics;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using dotnetcore_webapp.Models;
    
  3. Additionally, add the [Authorize] attribute directly above the HomeController class definition.

    [Authorize]
    

Add authentication and authorization to Program.cs

The Program.cs needs to be modified to add authentication and authorization to the web app. This includes adding namespaces for authentication and authorization, and being able to sign in users with the Microsoft identity platform.

  1. To add the required namespaces, open Program.cs and add the following snippet to the top of the file:

    using Microsoft.AspNetCore.Authentication.OpenIdConnect;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc.Authorization;
    using Microsoft.Identity.Web;
    using Microsoft.Identity.Web.UI;
    using System.IdentityModel.Tokens.Jwt;
    
  2. Next, add the authentication services to the application which will enable the web app to sign in users with the Microsoft identity platform. You can replace the rest of the code in Program.cs with the following snippet:

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.AddControllersWithViews();
    
    // This is required to be instantiated before the OpenIdConnectOptions starts getting configured.
    // By default, the claims mapping will map claim names in the old format to accommodate older SAML applications.
    // For instance, 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' instead of 'roles' claim.
    // This flag ensures that the ClaimsIdentity claims collection will be built from the claims in the token
    JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
    
    // Sign-in users with the Microsoft identity platform
    builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(builder.Configuration)
        .EnableTokenAcquisitionToCallDownstreamApi()
        .AddInMemoryTokenCaches();
    
    builder.Services.AddControllersWithViews(options =>
    {
        var policy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
        options.Filters.Add(new AuthorizeFilter(policy));
    }).AddMicrosoftIdentityUI();
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    
    app.UseRouting();
    app.UseAuthorization();
    
    app.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    
    app.Run();
    
    

Next step