Multi-tenant Azure AD Application

Create ASP.NET MVC application that authenticates against Azure AD

End-to-end walkthrough: How to Multi-tenant Application, register it with Azure AD, onboard tenants, go through the admin consent workflow, work with incremental [just-in-time] consent. All the code we write will be in C# and the application is an ASP.NET MVC application.

This is Step 2 of the series. To navigate to other articles in this series, look at the end of any article in the series for the list.


  • Microsoft Visual Studio 2019. You may use Community Edition, it is free for life. Alternately, you may use VS Code or any other IDE or tool, but you will have to modify the instructions in the article to suit your workflow.

You must have the following workloads installed:

This is what I am using:

You can sign up for the Preview by clicking the “Download Preview” link under the “Free download” button on this page.

Project Setup:

Fire up Visual Studio and create a new “ASP.NET Core Web Application“. I named the sample application “MultiTenantSample”. On the Configure project screen, I selected this:

Select “Web Application (Model-View-Controller)”, opt to have “No Authentication” (we will hook it all up manually) and “Configure for HTTPS”.

Now, we need to add some NuGet packages to our project before we can write the code. There are a 101 ways to do that, let’s do the simplest. I already know the packages I want. So, ensure the Solution Explorer tool window is open [Ctrl + W + S] and double-click on the project’s name:

Double-click on the project’s name.

The .csproj file’s Xml source will load. Replace ALL the content with the following:

<Project Sdk="Microsoft.NET.Sdk.Web">


  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <CodeAnalysisRuleSet />

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

    <PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.1.4" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.4" />
    <PackageReference Include="Microsoft.Azure.Storage.File" Version="11.1.7" />
    <PackageReference Include="Microsoft.Identity.Client" Version="4.14.0" />
    <PackageReference Include="Microsoft.Graph" Version="3.6.0" />
    <PackageReference Include="Microsoft.Azure.Cosmos.Table" Version="2.0.0-preview" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
    <PackageReference Include="SujaySarma.Sdk.Azure.Core" Version="1.5.0" />
    <PackageReference Include="SujaySarma.Sdk.Azure.Storage" Version="1.5.0" />
    <PackageReference Include="SujaySarma.Sdk.DataSources.AzureTables" Version="3.6.0" />


So, what did we do there?

  • We set up our project to target .NET Core 3.1
  • We set the language to C# 8.0
  • We turned ON the C# 8.0 nullable feature that lets us do NULL-safe programming.
  • We set up how we want our debug and release versions of code to be built — we also set our platform to target x64 (64-bit).
  • We added a whole bunch of NuGet packages.

Save the file and close the Xml editor. Visual Studio will restore all those packages [in the background] and install them into your project at this point. You don’t need to wait around for that.

NOTE: I have added the “Microsoft.AspNetCore.Mvc.NewtonsoftJson” and “Newtonsoft.Json” packages because there are some serializations that .NET Core’s “System.Text.Json” does not yet handle [or has bugs]. The Newtonsoft version does what we want to achieve and is performant enough.

Now, in order to make my work easier, I am using some of my own libraries, available as NuGet packages [and accompanying open-source code on Github]. These are the “SujaySarma.Sdk.*” packages.

Note that at this point, I have also performed some structural changes in my project. So any further screenshots of my project’s structure [folder tree, where certain files are] will be different from the Visual Studio provided one. However, these changes will not materially affect the walkthrough itself. These are as follows:

  • I have removed the directories under wwwroot special folder and used my own structure for arranging the jquery and bootstrap files.
  • I also like to use glyphicons, but they were removed from bootstrap 4.0 [which is what is in my github code]. So I have added the glyphicon styles and fonts from an earlier version of bootstrap.
  • Instead of capturing the values to IConfiguration and IWebHostEnvironment in a variable in the Startup class itself, I created a new static class called GLOBALS [all caps] and put them in there as static properties.
  • I have also declared a static CONSTANTS class and it contains some scope-constants and so on that we will use shortly. All of them have been documented — if you find an issue with the documentation, do let me know either here in comments or file an issue on the git repo.
  • I have edited the content the following files. Some changes are cosmetic while others have to do with mapping things to the rearrangements done as above:
    • Views/Shared/_Layouts.cshtml,
    • Views/Shared/_ValidationScriptsPartial.cshtml
    • Views/_ViewImports.cshtml
    • Views/_ViewStart.cshtml
  • Finally, I have removed the default controllers, views and models.

The code for this application is being hosted on GitHub here:

If you know how, you should fetch content up to [and including] commit 01a2e2c.

Other articles in this series:

Leave a Reply

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