DEV Community

David💻
David💻 Subscriber

Posted on

Implementing OWIN Authentication with Microsoft Entra ID in ASP.NET Framework

This article purpose is to describe how to secure your ASP.NET Framework application using OWIN middleware and Microsoft Entra ID (Azure AD) authentication. This comprehensive guide walks you through creating protected endpoints while maintaining public health checks for load balancers.

Requirements

  • Visual Studio 2022
  • Azure Subscription

Walkthrough

Creating the App Service

Within our Azure subscription, we will create an App Service of type Web App.
In the template, we will fill in basic data:

  • Select our Azure subscription
  • Create a resource group if one doesn't already exist
  • Give our application a name
  • We will publish the code directly from Visual Studio 2022
  • Our Runtime will be ASP.NET V4.8
  • Choose the Region and plan that best suits our needs
  • For this example, we will select a less crowded region and proceed with the Free plan

Proceed with the "Review + Create" option.

image1

Configuring the Default Domain

After our service has been created, we will navigate to the dashboard and copy the "Default Domain" value.

image2

Registering the Application in Microsoft Entra ID

Now we will navigate within our Azure Portal to Microsoft Entra ID > Manage > App Registrations.
Within this window, we will register the application by clicking the "New Registration" option.

In this window, we will:

  • Register the name of our application
  • Define which Tenants can access the application
  • Register the URI by copying the App Service application URL as "Web"

image3

Configuring Authentication

After having our application registered, in the same dashboard of our registered application, we navigate to Manage > Authentication.

In this window, we will activate the following options:

  • ID tokens (used for implicit and hybrid flows)
  • Access tokens (used for implicit and hybrid flows)

image4

Creating the Application in Visual Studio 2022

We will create a new project with the following template:

  • ASP.NET Web Application (.NET Framework)
  • Select runtime: .NET Framework 4.8

image5

image6

In the next window:

  • Select type: MVC
  • Authentication: None (because Azure will handle the authentication)
  • Uncheck "Configure for HTTPS"

image7

Installing Required Dependencies

Now we will proceed to install the necessary dependencies to run the project. Within the project:

Right-click > Manage NuGet Packages for Solution

Search for and install the following packages:

  • Microsoft.Owin.Security.OpenIdConnect
  • Microsoft.Owin.Security.Cookies
  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.IdentityModel.Protocols.OpenIdConnect

image8

Modifying Web.Config

After installing our dependencies, we start by modifying the Web.Config file.
Within appSettings, we proceed to modify the following values.

From Microsoft Entra ID, in App registrations, we look for our application and copy the following values:

  • ClientID
  • TenantID
  • RedirectUri (that we configured in App Service)

image8

<appSettings>
  <add key="webpages:Version" value="3.0.0.0" />
  <add key="webpages:Enabled" value="false" />
  <add key="ClientValidationEnabled" value="true" />
  <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  <add key="ida:ClientId" value="<your-client-id>" />
  <add key="ida:Authority" value="https://login.microsoftonline.com/<your-tenant-id>/v2.0" />
  <add key="ida:RedirectUri" value="https://<your-application>.azurewebsites.net/" />
</appSettings>
<system.web>
  <authentication mode="None" />
  <compilation debug="true" targetFramework="4.8" />
  <httpRuntime targetFramework="4.8" />
  <customErrors mode="Off"/>
</system.web>
Enter fullscreen mode Exit fullscreen mode

Creating Startup.cs

Now we will proceed with the creation of a file in the root called Startup.cs. What this file does is basically provide authentication control that sits in front of all requests.

using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
using System.Configuration;

[assembly: OwinStartup(typeof(TestAuthApplication.Startup))]

namespace TestAuthApplication
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = ConfigurationManager.AppSettings["ida:ClientId"],
                    Authority = ConfigurationManager.AppSettings["ida:Authority"],
                    RedirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"],
                    ResponseType = "code id_token",
                    Scope = "openid profile email",
                    TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidateIssuer = false
                    }
                });
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Creating Controllers

Now we proceed to create two controllers: a health check which will allow us to return a 200 response to the load balancer without needing authentication, and a protected page.

HealthCheckController.cs (No Authentication Required)

Within Controllers > HealthCheckController.cs:

using System;
using System.Web.Mvc;

namespace TestAuthApplication.Controllers
{
    [AllowAnonymous]
    public class HealthCheckController : Controller
    {
        public ActionResult Index()
        {
            return Json(new
            {
                status = "healthy",
                timestamp = DateTime.UtcNow,
                service = "TestAuthApplication"
            }, JsonRequestBehavior.AllowGet);
        }

        public ActionResult Ping()
        {
            return Content("OK");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

To prevent authentication, we define [AllowAnonymous].

ProtectedController.cs (Authentication Required)

Now we will proceed to create a protected page in Controllers > ProtectedController.cs:

using System.Web.Mvc;

namespace TestAuthApplication.Controllers
{
    [Authorize]
    public class ProtectedController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.UserName = User.Identity.Name;
            return View();
        }

        public ActionResult SecureData()
        {
            return Json(new
            {
                message = "This is protected data",
                user = User.Identity.Name
            }, JsonRequestBehavior.AllowGet);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

To require authentication, we define [Authorize].

Creating the View

Additionally, we can add a view for this in Views > Protected > Index.cshtml:

@{
    ViewBag.Title = "Protected Page";
}

<h2>Protected Page - Authentication Successful!</h2>
<p>Welcome, @User.Identity.Name!</p>
<p>You are successfully authenticated.</p>
<p>This page requires authentication to access.</p>
Enter fullscreen mode Exit fullscreen mode

Publishing to Azure

With our project ready, we will now proceed to publish it:

  • Right-click on the project > Publish > Azure
  • Authenticate with the user account that has access to our Azure subscription
  • Select our resource group and app service
  • Click Publish

image10

Testing the Application

Finally, we verify the access:

  1. Page without authentication requirement

Health check endpoint should return 200 without login

image11

  1. User authenticated in the tenant

Successfully accesses protected pages

image12

  1. User authenticated but not in the tenant

Receives access denied message

image13

Summary

Public endpoints (health check) that don't require authentication
Protected endpoints that require Azure AD authentication
OWIN middleware handling the authentication flow
Integration with Azure App Service for hosting

Top comments (0)