Why does AuthorizeAttribute redirect to the login page for authentication and authorization failures?

In ASP.NET MVC, you can mark up a controller method with AuthorizeAttribute, like this:

[Authorize(Roles = "CanDeleteTags")]
public void Delete(string tagName)
{
    // ...
}

This means that, if the currently logged-in user is not in the “CanDeleteTags” role, the controller method will never be called.

Unfortunately, for failures, AuthorizeAttribute returns HttpUnauthorizedResult, which always returns HTTP status code 401. This causes a redirection to the login page.

If the user isn’t logged in, this makes perfect sense. However, if the user is already logged in, but isn’t in the required role, it’s confusing to send them back to the login page.

It seems that AuthorizeAttribute conflates authentication and authorization.

This seems like a bit of an oversight in ASP.NET MVC, or am I missing something?

I’ve had to cook up a DemandRoleAttribute that separates the two. When the user isn’t authenticated, it returns HTTP 401, sending them to the login page. When the user is logged in, but isn’t in the required role, it creates a NotAuthorizedResult instead. Currently this redirects to an error page.

Surely I didn’t have to do this?

7 Answers
7

Leave a Comment