Securing Web API using Azure Easy Auth and Microsoft.Identity.Web

Vimal - Feb 12 - - Dev Community

This article is based on Microsoft Entra ID (Azure AD) as the identity provider.

Overview

Azure Easy Auth: Handles authentication for your App Service using Azure AD, Microsoft Entra ID, Google, Facebook, etc., without writing authentication code.
Microsoft.Identity.Web: A library to integrate Azure AD authentication in ASP.NET Core apps using the Microsoft Identity Platform (MSAL).

Scenario

For most use cases - no code change is required to integrate Easy Auth with your app, but for certain scenarios you might need to tweak the code a bit to make it work with the Microsoft.Identity.Web library.

Why do we need to tweak the application code?

1. Public and protected endpoints:

Azure App Service Easy Auth applies authentication at the gateway level. Every request will already be authenticated by the App Service, and your API endpoints will only see authenticated requests. This approach doesn’t allow you to differentiate between public and protected endpoints at the application level. If your requirement is to allow both authenticated and unauthenticated access (for e.g. health checks) for different endpoints at the app level, you can use an explicit [Authorize] attribute on endpoints requiring authentication. This also requires setting App Service's Easy Auth to permit unauthenticated requests to be forwarded to your API. For such scenarios set Restrict access to Allow unauthenticated requests on the App Service.

Easy Auth hybrid scenario

When you decorate an API endpoint with [Authorize], ASP.NET Core expects that an authentication middleware has been registered and configured with a default scheme. If no scheme is set up, you get an error message like:

"No authenticationScheme was specified, and there was no DefaultChallengeScheme found."

2. Claims and User Context:

In advanced scenarios you might need the user claims to make further authorization decisions. Without in-process authentication middleware, your API might not automatically have a fully populated HttpContext.User with the claims you might need for further authorization or logging. So even if you rely on Azure App Service Easy Auth to perform the initial authentication, configuring the in-process authentication scheme ensures that your API can correctly interpret and validate the authentication information (e.g., JWT tokens or mapped Easy Auth headers) and properly build the HttpContext.User.

3. Defense in Depth:

Relying solely on the fact that your App Service is being protected on a tenant level via Azure AD is not enough. Validating the token at the API layer provides an additional layer of security, making sure that even if the authentication infrastructure is compromised or misconfigured, your API won’t inadvertently accept invalid or forged tokens.

Here are the steps required to implement such custom scenarios:

🛠 Step 1: Enable Azure Easy Auth in App Service

  1. Configure Authentication in Azure Portal
  2. Go to Azure Portal → Navigate to your App Service
  3. In the left menu, go to Authentication
  4. Click Add identity provider
  5. Select Microsoft Entra ID (Azure AD)
  6. Choose Express Mode (or Advanced for custom settings)
  7. Click Save

Refer Easy Auth for more information

🛠 Step 2: Configure ASP.NET Core API with Microsoft.Identity.Web

Now, configure your API to validate the JWT tokens issued by Azure Easy Auth.

1. Install NuGet Packages

Run the following in your terminal to install the package:

dotnet add package Microsoft.Identity.Web
Enter fullscreen mode Exit fullscreen mode

2. Configure Authentication in Program.cs

Modify Program.cs to validate JWT tokens coming from Easy Auth:

using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);

// AddMicrosoftIdentityWebApi sets up the Bearer authentication handler.
builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddAuthorization();

var app = builder.Build();
//adds the authentication middleware to the request pipeline
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();
Enter fullscreen mode Exit fullscreen mode
  • AddMicrosoftIdentityWebApiAuthentication() sets up a handler and invokes token validation with parameters from your configuration.

  • app.UseAuthentication() invokes this middleware on each request, and if the token is invalid or missing, the request is rejected (typically with a 401 Unauthorized).

3. Configure appsettings.json

Replace with your Azure AD credentials in your appsettings.json:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "YOUR_TENANT_ID",
    "ClientId": "YOUR_APP_ID",
    "Audience": "api://YOUR_APP_ID"
  }
}
Enter fullscreen mode Exit fullscreen mode

TenantId → Found in Azure AD → Overview
ClientId → The App Service’s Application (client) ID
Audience → Should match the API’s Application ID URI

🛠 Step 3: Secure API Endpoints with [Authorize]

Modify your API controllers that require authentication using [Authorize] attribute.


using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/protected")]
[Authorize]

public class ProtectedController : ControllerBase
{
    [HttpGet]
    public IActionResult GetProtectedData()
    {
        return Ok(new { message = "You are authenticated via Easy Auth!" });
    }
}
Enter fullscreen mode Exit fullscreen mode

If a request does not include a valid token, it will return 401 Unauthorized.

🛠 Step 4: Get a Token and Test the API

1. Get a Token using Postman

For complete step-by-step guide to test the application using postman refer Test application using postman

Configure postman using steps listed in the above link and click Get New Access Token

  • This should return a JWT token in JSON format
  • Copy the id_token or access_token

2. Call the API with the Token

Use Postman or curl to call your API:

curl -X GET https://<your-app-name>.azurewebsites.net/api/protected \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

✅ If authentication is successful, the API should return 200 OK

❌ If you get 401 Unauthorized, ensure:
- The token is correctly passed in the Authorization header
- The API is correctly validating tokens

🛠 Step 5: Implement Role-Based Access Control (RBAC)

If you want to restrict access based on roles, update your controller with appropriate roles:

[Authorize(Roles = "Admin")]
[HttpGet("admin-only")]
public IActionResult AdminOnlyEndpoint()
{
    return Ok(new { message = "You are an admin!" });
}
Enter fullscreen mode Exit fullscreen mode
  1. Assign Users to Roles in Azure
  • Go to Azure Portal → Azure AD → App Registrations
  • Select your App Service
  • Navigate to App roles → Click Create app role
  • Fill in:
    • Display name: Admin
    • Allowed member types: Users/Groups
    • Value: Admin
    • Assign users under Enterprise Applications
  • Test the Role-Based API

    • Call /api/admin-only using a token from an Admin user
    • If the user lacks the Admin role, they will get 403 Forbidden

✅ Summary
✔ Easy Auth handles authentication (users log in via Azure AD).
✔ Microsoft.Identity.Web validates tokens in the API at the application level.
✔ Unauthenticated requests to API endpoints that do not require protection are allowed, enabling flexibility
✔ Only authenticated requests are allowed to API endpoints that require protection which are marked explicitly using [Authorize].
✔ RBAC restricts access based on roles.

. . . .