'Custom routes with custom authorisation policy

My application has 50 plus MVC controllers. Except one remaining should be protected. instead of decorating each and every controller with Authorize attribute, I created Authorisation policy and applied globally

app.MapControllers().RequireAuthorization(_requireAuthenticatedUserPolicy).

one controller I would like to bypass, I decorated as AllowAnonymous.

My issue is with inbuilt healthcheck package which I do not have control. If I use inbuilt healthcheck check method to register health check route, AllowAnonymous is not applying automatically.

app.MapHealthChecks("/health") 

This is the breaking change in ASP.NET Core 6. This was working properly in ASP.NET Core 5

ASP.NET Core 5.0

//Configure method ASP.NET Core 5 - working
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");

    endpoints.MapControllers()
    .RequireAuthorization(_requireAuthenticatedUserPolicy);
});

ASP.NET Core 6.0 Below is the code in in ASP.NET Core 6. Auth policy is applying on health check route as well.

var app = builder.Build();

/* other code */
app.MapHealthChecks("/health");

app.MapControllers()
    .RequireAuthorization(_requireAuthenticatedUserPolicy);

Any changes in ASP.NET Core 6 routing and order? How to exclude routes in auth policy?

Edit 1

@JeremyLakeman comment solved the problem. I didn't realize that AllowAnonymous extension method exist.



Solution 1:[1]

For controllers that you do not want to have the auth policy apply to, the [AllowAnonymous] attribute for the controller or method should do the trick if it is the exception. Just making sure you are trading one attribute flooding your controllers for another.

If you want to do it all in the startup, you may have to do some more digging if you want it to work without any decoration or you can just specify a different auth policy specifically for that route.

For instance:

            endpoints.MapGet("/health", async context =>
            {
                await context.Response.WriteAsync("Hello World!");
            }).RequireAuthorization("FirstAuthPolicy", "SecondAuthPolicy");


            endpoints.MapGet("/Foo", async context =>
            {
                await context.Response.WriteAsync("Hello World from a second place!");
            }).RequireAuthorization("ThirdAuthPolicy");

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ben Matthews