Minimal Code to Protect Web API with Azure AD

In this post we can see the most minimal code to protect a Web API with Azure AD.

This protected Web API can be used for both:

  • Frontend Flow with ID Token
  • Backend Flow with Access Token

Create App Registration

Create App Registration with ID Token & Access Token enabled.

Note down the Client ID & Tenant ID

Create Web API Project

Create a .net core web application, add a ToDo controller into it with get & post methods.

Configuration add the following section into app.config

“AzureActiveDirectory”: {
   “Instance”: “https://login.microsoftonline.com/”,
   “TenantId”: “YOUR-TENANT-ID”,
   “ClientId”: “YOUR-CLIENT-ID”
}

Startup Code

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Cors.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace WebAPI
{
     public class StartupTest
     {
         public StartupTest(IConfiguration configuration)
         {
             Configuration = configuration;
         }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
         {
             var options = new AzureADOptions();
             Configuration.Bind(“AzureActiveDirectory”, options);

            services.AddAuthentication(op => { op.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; })
             .AddJwtBearer(op =>
             {
                 op.Authority = options.Instance + options.TenantId;
                 op.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                 {
                     ValidAudience = options.ClientId,
                     ValidateIssuer = false,
                     ValidateIssuerSigningKey = false
                 };
             });

            services.AddCors(o => o.AddPolicy(“MyPolicy”, builder =>
             {
                 builder.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader();
             }));

            services.AddMvc();
             services.Configure<MvcOptions>(op =>
             {
                 op.Filters.Add(new CorsAuthorizationFilterFactory(“CorsPolicy”));
             });
         }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
         {
             if (env.IsDevelopment())
             {
                 app.UseDeveloperExceptionPage();
             }
             else
             {
                 app.UseHsts();
             }

             app.UseHttpsRedirection();
             app.UseCors(“MyPolicy”);
             app.UseAuthentication();
             app.UseMvc();
         }
     }
}

Controller Code

[Authorize]
    [ApiController]
    [Route(“api/[controller]”)]
    [EnableCors(“CorsPolicy”)]
    public class TodoListController : ControllerBase

Testing

You can create a Client App with the same Client ID and get the ID Token to access the API.

You can create a Postman Request with same Client ID & Client Secret and get the Access Token to access the API.

Azure Active Directory Learnings–Zero to Production

In this post I would like to note down the AAD aspects.  This would be helpful for anyone who wanted to Integrate Authentication & Authorization with their applications.

Azure Active Directory

AAD is an Identity management system hosted in Microsoft Azure cloud.  It can offer authentication & authorization for applications.

AAD can provide Authentication & Authorization for Web Applications, Desktop Applications & Mobile Applications as well.

OAuth2 & OpenID Connect

OAuth2 is an Authorization protocol.

OpenID Connect can be used for both Authentication & Authorization

Comparison of SAML vs OAuth2 vs OIDC

image

App Registration for Frontend

App Registration + ID Token

App Registration for Backend

App Registration + Client Credential Flow

App Registration for Frontend & Backend

App Registration + ID Token + Access Token

Pro-Tools

Following are few tools than can help in your adventure:

Azure AD Error–Invalid Grant–Application is not assigned to a Role for applciation

ERROR

“error”: “invalid_grant”,

“error_description”: “AADSTS501051: Application ‘5669c008-20c0-4118-AAAAAAA(APP-01) is not assigned to a role for the application ‘5669c008-20c0-4118-8f45-AAAAAAAA'(APP-01).

“error_codes”: [501051]

SOLUTION 1

Go to Portal > Active Directory > Enterprise Applications > > Choose your App > Set User assignment required to No

image

SOLUTION 2

Go to Users > Add User

Azure App Identity & Service Principal

Azure Service Principal is a Security Identity used for Apps & Background Services.  It will accomplish the Role of a User Identity require by Applications.  It is similar to Service Accounts of Windows in the past.

Advantages

Advantages of App Identity are following:

  • Allow multiple Apps to use the Same Identity
  • Can use Certificate to Authenticate instead of Passwords
  • No Password expiry overheads
  • Can restrict read/write access

image On App Registration two objects are create – App object & Service Principal object.

Setting Access at Subscription Level

We can set Access to the Service Principal object at the Subscription level.  Go to Home > Subscriptions > Access Control (IAM)

image

In the appearing window choose the App Registration created jus now & Select the Role.

image

Save changes for completing the Role assignment.

Access Scope

Access Scope is set at the following levels.

  • Subscription Level
  • Resource Group Level
  • Resource Level

References

https://docs.microsoft.com/en-us/azure-stack/operator/azure-stack-create-service-principals?view=azs-1910

Enable Azure Active Directory for a .Net Core 2.2 Web Application

In this article we can see how to configure Azure Active Directory for a .Net Core 2.2 Web Application.

Step 1: Create new Web Application

Create new Web Application of .Net Core 2.2 version.

image

Add Nuget Package following:

  • Microsoft.IdentityModel.Clients.ActiveDirectory

image

Step 2: Run the Application

Run the application & Copy the URL of it.

Step 3: App Registration

You can Refer this application below.

https://jeanpaul.cloud/2019/12/13/how-to-do-app-registration-for-enterprise-application/

Step 4: App User

Add a new user to the Enterprise Application.

Step 5: Modify the Configuration File

Modify the Configuration File as following:

{
   “Authentication”: {
     “ClientId”: “CLIENT ID FROM APP REG”,
     “ClientSecret”: “CLIENT SECRET FROM APP REG”,
     “Authority”: https://login.microsoftonline.com/ACTIVE DIRECTORY GUID,
     “PostLogoutRedirectUri”: “https://localhost:44372/”,
     “CallbackPath”: “/signin-oidc”,
     “ResponseType”: “code id_token”
   }
}

Leave the last 2 parameters as it the default OIDC middleware parameters.

Step 6: Replace Startup.cs

Replace Startup.cs with the following code.

(mainly the changes are in ConfigureServices() and Configure() method)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Clients.ActiveDirectory;

namespace AADenableBlog
{
     public class Startup
     {
         public Startup(IConfiguration configuration)
         {
             Configuration = configuration;
         }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
         public void ConfigureServices(IServiceCollection services)
         {
             services.AddAuthentication(auth =>
             {
                 auth.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                 auth.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
             })
               .AddCookie()
               .AddOpenIdConnect(opts =>
               {
                   Configuration.GetSection(“Authentication”).Bind(opts);

                  opts.Events = new OpenIdConnectEvents
                   {
                       OnAuthorizationCodeReceived = async ctx =>
                       {
                           HttpRequest request = ctx.HttpContext.Request;

                          string currentUri = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path);
                           var credential = new ClientCredential(ctx.Options.ClientId, ctx.Options.ClientSecret);

                          var authContext = new AuthenticationContext(ctx.Options.Authority);

                          string resource = “https://graph.microsoft.com”;
                           AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(
                               ctx.ProtocolMessage.Code, new Uri(currentUri), credential, resource);

                          ctx.HandleCodeRedemption(result.AccessToken, result.IdToken);
                       }
                   };
               });

            services.Configure<CookiePolicyOptions>(options =>
             {
                 options.CheckConsentNeeded = context => true;
                 options.MinimumSameSitePolicy = SameSiteMode.None;
             });

             services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
         }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
         {
             if (env.IsDevelopment())
             {
                 app.UseDeveloperExceptionPage();
             }
             else
             {
                 app.UseExceptionHandler(“/Home/Error”);
                 app.UseHsts();
             }

            app.UseHttpsRedirection();
             app.UseStaticFiles();
             app.UseAuthentication();
             app.UseCookiePolicy();

            app.UseMvc(routes =>
             {
                 routes.MapRoute(
                     name: “default”,
                     template: “{controller=Home}/{action=Index}/{id?}”);
             });
         }
     }
}

Step 7: Modify Controller

Modify the Home Controller as following:

[Microsoft.AspNetCore.Authorization.Authorize]

public class HomeController : Controller

// This will ensure Login prompt will prompt whenever the Controller method is accessed.

Step 8: Run the Application

Run the application & It should prompt you for the Login.  Enter the Credentials.

You can see the Login prompt.

image

Enter your New User credentials and you will be redirected to the Home Screen.

Download

The source can be downloaded here.

https://azuretrendz.files.wordpress.com/2019/12/aadenableblog.zip

Summary

In this article we have seen how to configure Azure Active Directory for a .Net Core 2.2 Web Application.

How to do App Registration for Enterprise Application?

In this post we can see how to do an App Registration for a Web application so that it will become Enterprise Application.

Step 1  Open Azure Portal > Active Directory

Open Azure Portal > Go to Active Directory from Resources.

image

Step 2  Open App Registrations

Open App Registrations blade as shown below.

image

Step 3 Create New App Service

Click on the New Registration button. 

  • Enter Name for the service
  • Leave the default options
  • Enter the Redirect URI as the URL of your web application / web api

Click the Register button

Copy the Client ID  as displayed over there.

image

Step 3 Create Credentials

Go to the Certificates & secrets blade. 

  • Click on New client secret
  • Save changes

Copy the Password generated

image

Now you have the Client ID and the Client Secret for the App Registration.  Now any application authenticated using these will be given privilege of this App Registration.

Step 4  Open Enterprise Applications

Open Enterprise Applications blade from Active Directory.  Search for the name.

image

If you can find your Application – Congratulations!

You have just created an Enterprise Applications.  Now you can do the following & more with it.

  • Add Owners
  • Add Users
    • Internal & External
    • Enable Self-Servcie
  • Audit Logs
  • Troubleshoot

References

https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/what-is-application-management

Summary

In this post we have seen how to perform an App Registration.

OAuth2 vs OpenID Connect & Azure AD Seamless SSO

OAuth 2 is an Authorization Framework.  It allows 3rd party application to get access to an HTTP Service.  It is primarily used as Token for API Access.

OpenID Connect is an Authentication Framework.  It is primarily used as ID Token for SSO.

Azure AD Seamless SSO automatically signs in users from their corporate devices to Azure Active Directory.

References.

Internet Engineering Task Force https://tools.ietf.org/html/rfc6749