Introduction
When modernising your enterprise ASP.NET (.NET Framework) or ASP.NET Core applications and moving them from IIS over to Azure App Service, one of the aspects you will have to take into consideration is how you will manage authentication (AuthN) and authorisation (AuthZ). Specifically, for applications that leverage on-premises auth mechanisms such as Integrated Windows Authentication, you will need to start considering more modern auth protocols such as OpenID Connect/OAuth which are more suited to the cloud.
Fortunately, App Service includes built-in authentication and authorisation support also known as 'Easy Auth', which requires minimal to zero code changes. This feature is integrated into the platform, includes a built-in token store, and operates as a middleware running the AuthN logic outside of your code logic, as illustrated by the image below:-
More information on how EasyAuth works can be found here.
Easy Auth supports several providers as illustrated above, but in this blog we will purely focus on using Entra ID (formerly known as Azure Active Directory) as the provider. It also assumes all of the Active Directory users have been synced up to Entra ID.
With a few clicks, you can enable Entra ID authentication across any of your web, mobile or API apps in App Service, restrict which tenants or even specific identities are allowed access – all without touching code. This can be quite powerful in many scenarios, such as when you do not have access to the source control to implement your own auth logic, reducing the maintenance overhead of maintaining libraries or simply want a quick path to apply auth across your apps. For more detailed scenarios and comparison on when it makes sense using Easy Auth versus other authentication methods can be found here.
Setting up Easy Auth
Let’s see Easy Auth in action. As you can see below I have a sample ASP.NET app hosted on App Service which is accessible without any authentication:-
Now let’s demonstrate how quickly it is to setup Easy Auth for my app:-
1) I navigated to my App Service resource within the Azure Portal
2) I went to Authentication and used the below configuration
o Selected Microsoft as the Identity provider
o Workforce configuration (current tenant)
o Create a new app registration (appropriate Entra ID roles are required)
o Entra ID app name:- sot-easyauth
o Client secret expiry:- 180 days (this means I must renew the secret in advance of the 180 days otherwise my app/authentication will fail to function upon expiry causing downtime).
o Allow requests only from this application itself.
o Current tenant – Single tenant (i.e users outside of my tenant will be denied access)
o Identity requirement:- Allow requests from any identity
o Restrict access:- Require authentication (this will require authentication across my whole app, whereas “Allow unauthenticated access” means it is up to my app to decide when authentication is required).
o HTTP 302 Found redirect (redirects unauthenticated users to the login page rather than just a page stating 401 unauthorised for example).
o Token store:- Enabled (also allows the app to have access to the token).
3) For permissions, I left the default User.Read Graph API permission selected. More information on the different permissions can be found here.
Now if I go back to the app and refresh the page again, I am redirected to the login page which is surfaced by the Easy Auth middleware:-
Only after successful authentication, will I be able to see the Welcome page again:-
Now that is pretty impressive, but you might want to go even further and have questions such as: how will my app know who’s logged in? How can I access the claims? How do I perform more granular AuthZ? Well for starters, Easy Auth essentially creates the claims in the incoming token and exposes them to your app as request headers which your app can then leverage to interpret accordingly. The list of headers can be found here. Typically, you will be tasked with creating custom logic to decode and interpret these claims, but with the likes of ASP.NET (.NET Framework), App Service can populate the claims of the authenticated user without additional code logic. However for ASP.NET Core this does not hold true. Thus, given the approach differs between ASP.NET (.NET Framework) and ASP.NET Core (starting from .NET Core), I will split these up into two different sections after touching upon AuthZ and Entra ID app roles.
AuthZ and Entra ID App Roles
If your IIS ASP.NET app leverages Windows Authentication for AuthN, but your app manages AuthZ itself, perhaps by mapping the domain credentials (e.g. CONTOSO\Sam) to specific AuthZ roles stored in somewhere like a database and remains a requirement to do, you can achieve a similar outcome by using the claims provided by Easy Auth. However, it is not recommended to use fields such as domain credentials, e-mail or UPN (e.g. dan.long@contoso.com) given such attributes can change and even be re-used over time. For example, an employee called Dan Long has the UPN of dan.long@contoso.com leaves the company and another employee with the same name joins the company and is assigned the same UPN dan.long@contoso.com – potentially giving unauthorised access to resources belonging to the former employee. Instead you may consider using the oid (i.e objectId), which is a globally unique GUID that identifies the user across applications within a single tenant. You might also consider pairing oid with tid (i.e tenant ID) for sharding/routing if required. A note for multi-tenancy applications: the same user that exists in different tenants will have a different oid. More information on how to reliably identify a user and the different claim types available can be found here.
Alternatively, if the built-in authorisation policies do not suffice, you can leverage Entra ID app roles to apply authorisation within your ASP.NET App, which we will cover in more depth further down below. For demonstration purposes, I have created an app role called Member in my Entra ID App Registration and assigned the Entra ID group “Contoso EA Members” to this role via the associated Entra ID Enterprise Application, which my identity is part of as shown below:-
I am leveraging said role to restrict only the role Member from being able to access the Member Area page (more on this further down).
More information on creating your own Entra ID app roles can be found here.
ASP.NET (.NET Framework) claims and Entra ID App roles
For ASP.NET 4.6 apps, App Service populates the user’s claims through ClaimsPrincipal.Current, which means you can easily reference the claims without additional logic. I have created sample code which demonstrates this here, and the output of this in App Service can be found below:-
You will notice Easy Auth has picked up my Entra ID app role called Member under claim type roles. In the screenshot and sample, you will notice I have a link located on the top nav bar called Member Area which is guarded by an [Authorize] tag to restrict only members with the role Member access. Unfortunately, at this stage, if we were to access the page it will return with 401 Access Denied, regardless of my identity having the appropriate app role. The reason behind this, is because ASP.NET is looking for the claim type “http://schemas.microsoft.com/ws/2008/06/identity/claims/role” instead of “role”. Fortunately, Easy Auth can be configured to display the long claim name instead by configuring the Environment Variable WEBSITE_AUTH_USE_LEGACY_CLAIMS to False, as shown in the below screenshot:-
After the change, if I logout and back in again, I will see this being reflected back into my application and the Member Area page will grant me access as shown in the screenshots below:-
Voila, we now have claims and Entra ID app roles working within our ASP.NET application.
ASP.NET Core claims and Entra ID App roles
Out-of-the-box, Easy Auth does not support populating ASP.NET Core with the current user’s authentication context like it does for ASP.NET (.NET Framework) with ClaimsPrincipal. However, this can be achieved by using the nuget package Microsoft.Identity.Web which has built-in capability to achieve this.
What I did was as follows:-
1) Installed the nuget package Microsoft.Identity.Web into my solution.
2) In my Program.cs file, I loaded in the library:-
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration);
3) I also added app.UseAuthorization() after app.UseAuthentication()
app.UseAuthentication();
After these changes, User.Identities will now be populated with the claims, and the [Authorize] tag will work permitting only the role Member when visiting the Member Area page.
The full sample code can be found here.
Unlike with ASP.NET (.NET Framework), the downside with this approach is the added responsibility of managing an additional library (Microsoft.Identity.Web).
Conclusion
App Service Easy Auth can provide a streamlined and efficient way to manage authentication and authorisation for your ASP.NET applications. By leveraging Easy Auth, you can apply modern auth protocols with minimal to zero code changes. The built-in support for various identity providers, including Entra ID, can help developers implement flexible and robust auth mechanisms. As demonstrated, Easy Auth simplifies the process of integrating authentication and authorisation into your applications, making it an valuable tool for modernising enterprise apps.
Good to know and additional resources
- Limitations of Entra ID app roles. For example “A user, group, or service principal can have a maximum of 1,500 app role assignment”:- Service limits and restrictions - Microsoft Entra ID | Microsoft Learn.
- You can leverage Azure Policy to audit across the organisation when App Service does not have Easy Auth enabled by turning on “App Service apps should have authentication enabled”:- Built-in policy definitions for Azure App Service - Azure App Service | Microsoft Learn.
- Work with User Identities in AuthN/AuthZ - Azure App Service | Microsoft Learn
- Configure Microsoft Entra Authentication - Azure App Service | Microsoft Learn
- Work with OAuth Tokens in AuthN/AuthZ - Azure App Service | Microsoft Learn