C#: Modify Claims via Middleware in ASP.NET

kenakamu

Kenichiro Nakamura

Posted on July 27, 2022

C#: Modify Claims via Middleware in ASP.NET

Most Web applications use OAuth 2.0 to authenticate/authorize uses these days. ASP.NET also has built-in support for OAuth 2.0 with Azure AD which we use quite often.

However, in many projects, we found it difficult to include appropriate claims from the beginning because:

  • Management team of AD is different
  • There are strict policies that we cannot create test AD
  • We don't know what scope to be created yet

In such care, we often neglect authorization settings in controller, but we shouldn't. To avoid this, I explain how to use middleware to modify passed claim so that we can tweak JWT.

There are several things to keep in our mind. (Great comment by @phlash909)

  • If we modify JWT in this way, we cannot pass it to another service anymore.
  • We can also offload this to another service, rather than directly modify claims to keep it clean.

Web API

In this article, I start from normal Web API using template.



dotnet new webapi -n modifyjwt
cd modifyjwt
start .\modifyjwt.csproj


Enter fullscreen mode Exit fullscreen mode

Enable Authentication

Refer to Quickstart: Protect a web API with the Microsoft identity platform to enable authentication against your Azure AD.

Add require scope to existing controller

By default, there are not authorization settings in existing controller.

1. Install Microsoft.Identity.Web nuget package.

2. Add [RequiredScope] attribute to WeatherForecastController.cs. I added ReadWeatherForecast as required scope.



[HttpGet(Name = "GetWeatherForecast")]
[RequiredScope("ReadWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = Random.Shared.Next(-20, 55),
        Summary = Summaries[Random.Shared.Next(Summaries.Length)]
    })
    .ToArray();
}


Enter fullscreen mode Exit fullscreen mode

3. Run the application and confirm you cannot access the controller.
Failed to access with 404 unauthorized

Add middleware to modify JWT

1. Add middleware class.



using System.Security.Claims;

namespace modifyjwt;

public class MyAuthMiddleware
{
    private const string SCOPE_CLAIM_TYPE = "http://schemas.microsoft.com/identity/claims/scope";
    private readonly RequestDelegate _next;

    public MyAuthMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        if (context.User.Identity is not null
            && context.User.Identity.IsAuthenticated)
        {
            Claim scope = context.User.Claims.First(x => x.Type == SCOPE_CLAIM_TYPE);
            (context.User.Identity as ClaimsIdentity)?.RemoveClaim(scope);
            context.User.AddIdentity(new ClaimsIdentity(new List<Claim>()
            {
                new Claim(SCOPE_CLAIM_TYPE, "ReadWeatherForecast"),
            }));
        }

        // Call the next delegate/middleware in the pipeline.
        await _next(context);
    }
}

public static class MyAuthMiddlewareExtensions
{
    public static IApplicationBuilder UseMyAuthMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<MyAuthMiddleware>();
    }
}


Enter fullscreen mode Exit fullscreen mode

2. Use it in Program.cs between UseAuthentication and UseAuthorization



app.UseAuthentication();

app.UseMyAuthMiddleware();

app.UseAuthorization();


Enter fullscreen mode Exit fullscreen mode

3. Run the app to confirm it works.

Success to get data

Add multiple scopes

If we need to add multiple scopes, we can add it by separate each scope with space like ReadWeatherForecast WriteWeatherForecast.

Summary

In production, we should get all necessary scopes from Azure AD, or at least fetch from data source by using user id.

💖 💪 🙅 🚩
kenakamu
Kenichiro Nakamura

Posted on July 27, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related