Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does anyone have a good explanation on how the [Authorize] Attribute handles routes in a standard ASP.NET MVC 5 application?

As you can see from my previous post, I've been having a lot of difficulty with MVC 5's [Authorize] attribute. The dev team in the shop next door can't figure out why the attribute keeps failing in every new project I create in Frameworks 4.5.2, 4.5.3, or 4.6 (By fail, I mean that decorating an action method with the attribute will automatically redirect all users, authorized or no, to a 401 page). My new standard practice is to create a custom attribute inheriting from AuthorizeAttribute in every membership system I build, but this is obviously not ideal.

MSDN doesn't have any code-based explanation of how the attribute actually reroutes unauthorized users to the login page (the expected behavior), which is the critical insight that's needed in order to determine whether the true bug lies in my codebase, or is instead a quirk in the IIS host settings. Anyone out there able to white-box this attribute once and for all?

like image 641
Kanapolis Avatar asked Oct 13 '15 15:10

Kanapolis


2 Answers

Remember that authentication and authorization are separate concerns in your application.

Basically you're going to need to implement an IAuthenticationFilter

Have a look at the MVC5 pipeline http://www.dotnet-tricks.com/Tutorial/mvc/LYHK270114-Detailed-ASP.NET-MVC-Pipeline.html - there have been a number of changes since MVC4 Pipeline
(source: dotnet-tricks.com)

Most importantly is the introduction of the Authentication filter. Previously they combined the Authentication and the Authorization handling into the [Authorize] filter, now they have separated these concerns out properly.

There is a nice article by James Chambers that should give you a good overview of how these filters behave in the lifecycle of a request: http://jameschambers.com/2013/11/working-with-iauthenticationfilter-in-the-mvc-5-framework/

Throwing an UnAuthorized result should do it:

public void OnAuthentication(AuthenticationContext filterContext)
{
    if (!filterContext.Principal.Identity.IsAuthenticated)
        filterContext.Result = new HttpUnauthorizedResult();
}

In an MVC application the default mechanism for authentication is Forms, for which there is a default account controller and corresponding views added to our project. Thus, by simply letting the user “fall through”, they will end up at the login page.

Hope that helps :)

like image 113
ShaunP Avatar answered Nov 16 '22 11:11

ShaunP


First, the ASP.NET version really has nothing to do with anything. About the only thing you might experience between switching framework versions is certain methods may be deprecated or added. However, there's very little variation between any of the 4.5 dot-releases and for your purposes here, very little change going to 4.6.

For the Authorize attribute in particular, the only thing of relevance is your version of MVC since it's part of MVC. Since that remains constant, you're not really doing anything by trying to switch framework versions.

As for how it routes, it's pretty straight-forward. 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. For Forms Auth / Identity, it will redirect to the login page, for HTTP digest it will pop up the browser-based login modal, etc.

Long and short, if you're getting redirected that means Authorize is returning 401, and if it's returning 401 that means the user is not authorized. Plain and simple. It may be that the user doesn't have the roles you think it does, the user is not actually logged in (a common problem with Windows Auth on a machine that is not properly joined to a domain or has otherwise lost connectivity with AD), etc.

like image 27
Chris Pratt Avatar answered Nov 16 '22 10:11

Chris Pratt