Active Directory Web API Application Authentication by passing JWT token from an MVC application to MVC Web API application Edit

Murugan Andezuthu Dharmaratnam | 18 August 2021 | 379

Here we have two application. MVC application with front end UI and a backend asp .net mvc web api application. In this article we will discuss about how to authenticate the web api application using the token from asp .net mvc front end application. Front end application stores the token and when it makes a get request to the backend web api application it sends the token from front end application as authorization bearer token in the http header.

Active Directory Application Registration

First thing to do is to register two applications registered two applications in Active directory. Please follow the below steps to complete application registration in Active directory. Once Application Has been registered and you have the clientid, tenentid & client secret.

Backend
- Register Application
	Name: poc-backend-dev
	 Redirect URI : Leave it Blank 
- Please Save it for use in application code
	- Application (client) ID
	- Directory (tenant) ID
- Expose an API ( Left Menu )
	  Add A Scope
		- Application Id Url : Default Value
		- Click On Save & Continue 
		 
		- Scope Name : api-access
		- Who can consent?: Admin & Users
		- Admin consent display name : api-access-backend
		- Admin consent description : api-access description (some text )
		- State: Enable
		- Click on Add Scope
	- Please copy the Scopes from the newly added scope and save it for use in application ( It will be similar to api://38250f66-549c-4908-9f6a-d9f382a******/api-access )
	


Client
- Register Application
	Name: poc-client-dev
	 Redirect URI : https://localhost:44305/signin-oidc ( change to your url in dev and for production also change it )
- Authentication ( Left menu )
	- Front-channel logout URL :  https://localhost:44305/signout-oidc	( change to your url in dev and for production also change it )
- Certificates & Secrets ( Left Menu )	
	-   New Client Secrets
		- Enter some description
		- Expires : 6 Months
		- Click On Add
		- Copy Secrets value 
- Please Save it for use in application code
	- Application (client) ID
	- Directory (tenant) ID
	- Client secret Value 
- API permissions ( Left Menu )
	-    Add A Permission
		- Select MY API's
			- Click On backend application
			- What type of permissions does your application require? : Delegated Permission
			-  Permissions Check api-access Click On Add Permission
	- Click On Grand admin consent for Default Directory
		- Click Yes

Client App

You need two asp .net mvc applications. Front end asp .net mvc application and an asp .net mvc web api application. We will login using our email and password using Active directory in asp .net mvc front end application. Then we will get the token in pass it on the asp .net background web api application. Make the following changes to the asp .net mvc application.

appsettings.json

update AD details in the appsettings.json file. Do not forget to add the ClientSecret

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "******4beginner.onmicrosoft.com",
    "TenantId": "8e5da8dc-f3fb-4c5f-985a-7f0d33f*****",
    "ClientId": "a18c2ef1-0f6d-4e0f-8270-6d6648e*****",
    "CallbackPath": "/signin-oidc",
    "ClientSecret": "8fVA~xlR034_XUH2FLZ.tYUp3f_E******"
  },

}

HomeController.cs

We will add code in Home controller index method to get and store token in a static variable. When the user clicks on Privacy from the main menu or footer we will make a get request to the background web api application to return the value.

private readonly ITokenAcquisition tokenAcquisition;

public HomeController(ILogger logger, ITokenAcquisition tokenAcquisition)
{
    _logger = logger;
    this.tokenAcquisition = tokenAcquisition;
}



public static string access_token { get; set; }
public IActionResult Index()
{
    string[] scopes = new string[] { "user.read", "api://5fef7977-9f4c-41e6-9159-5a17380******/api-access" };
    access_token = tokenAcquisition.GetAccessTokenForUserAsync(scopes).Result;
    return View();
}

[HttpGet]
public IActionResult Privacy()
{
    HttpClientHandler clientHandler = new HttpClientHandler();
    clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
    var httpClient = new HttpClient(clientHandler);
    
    Common.token_mapping.TryGetValue(User.Identities.First().Name, out access_token);
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", access_token);
    var response = httpClient.GetAsync("https://localhost:44370/WeatherForecast").Result;
    var retval = response.Content.ReadAsStringAsync().Result;
    ViewBag.OPARetval = retval;
    return View();
}




Statrup.cs

We need to make come changes in configuration to store the token in memory & services.Configure<ForwardedHeadersOptions>.NET to fix issue of Core Azure AD in Docker Container Incorrectly Uses a non-https redirect URI

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi(new string[] { "user.read" })
    .AddInMemoryTokenCaches();

    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                      ForwardedHeaders.XForwardedProto;
        // Only loopback proxies are allowed by default.
        // Clear that restriction because forwarders are enabled by explicit
        // configuration.
        options.KnownNetworks.Clear();
        options.KnownProxies.Clear();
    });

}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseForwardedHeaders();
}

WEB API Background Service Application

Background service web api application is simple. add to appsettings.json . Here you don't need the client ID.

  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "****4beginner.onmicrosoft.com",
    "TenantId": "8e5da8dc-f3fb-4c5f-985a-7f0d33f*****",
    "ClientId": "5fef7977-9f4c-41e6-9159-5a17380*****"
  },