When using ASP.Net WebAPI, I used to have a custom Authorize
attribute I would use to return either an HTTP 403
or 401
depending on the situation. e.g. if the user is not authenticated, return a 401
; if the user is authenticated but doesn't have the appropriate permissions, return a 403
. See here for more discussion on that.
It seems now, in the new ASP.Net Core, they don't want you overriding the Authorize
attribute anymore instead favoring a policy-based approach. However, it seems Core MVC suffers from the same "just return 401
for all auth errors" approach its predecessors have.
How do I override the framework to get the behavior I want?
Authorization in ASP.NET Core is controlled with AuthorizeAttribute and its various parameters. In its most basic form, applying the [Authorize] attribute to a controller, action, or Razor Page, limits access to that component to authenticated users. Now only authenticated users can access the Logout function.
The Authorize attribute actually doesn't route anywhere; all it does is return a status code of 401 or 403 if the user is not authorized. The MVC framework takes over at that point and takes the appropriate steps to authorize the user based on the authentication scheme in use.
I ended up doing it with middleware:
public class AuthorizeCorrectlyMiddleware { readonly RequestDelegate next; public AuthorizeCorrectlyMiddleware(RequestDelegate next) { this.next = next; } public async Task Invoke(HttpContext context) { await next(context); if (context.Response.StatusCode == (int)HttpStatusCode.Unauthorized) { if (context.User.Identity.IsAuthenticated) { //the user is authenticated, yet we are returning a 401 //let's return a 403 instead context.Response.StatusCode = (int)HttpStatusCode.Forbidden; } } } }
which should be registered in Startup.Configure
before calling app.UseMvc()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With