Authentication and Authorization in Asp.Net MVC

Authentication and Authorization in Asp.Net MVC

Introduction

Asp.Net MVC has been there in the market for more than a decade now and it is still the preferred choice of developing web applications with .NET Framework. There are lots of applications running in Asp.Net MVC in production. Although there has been a demand of migrating the .NET Framework to AspNetCore it is always better to understand how the technology got evolved into what it is now.

In this post we will understand the process of doing authentication and authorization in asp.net mvc application. We would be looking into FormsAuthentication specifically.

In our previous post we discussed the basics of What is Authentication and Authorization and How authentication and authorization works in asp.net particularly in Asp.Net WebForms Application.

You can refer to my previous post from the link below.
Understanding Authentication and Authorization in Asp.Net WebForms

Authentication and Authorization

As we already know from our previous post that Authentication answers the question Who the User is ? and Authorization andswers the questions What the User has access to ?

Authentication and Authorization is needed to keep our web application secure and thus it is very important to know this process in depth.

Well, Authentication works the same way in MVC as it works in the Asp.Net WebForms. The below mentioned steps holds true in MVC as well.

  1. Specifying the Authentication Mode
  2. Validating the credentials
  3. Generating the Authentication Cookie
  4. Setting the value of the HttpContext.User property
  5. Using the HttpContext.User property for Authorization

If you want want to know about these steps further click here to go to my previous post.

Now we will specifically focus on things which are different in MVC.

[Authorize] Attribute

[Authorize] attribute is an attribute that can be placed on top of a controller or an action method.
If this attribute is placed on top of controller all the action methods defined inside the controller has authorization enabled by default.
This means that user not having the required access level would be restricted and would be redirected to the referrer or login url as specified.

Let us look into the code of the [Authorize] attribute to undertsand it better. We will not go through the entire class but we will look into the two most important methods in the implementation.

public virtual void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
            {
                throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
            }

            if (!filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true) && !filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true))
            {
                if (AuthorizeCore(filterContext.HttpContext))
                {
                    HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
                    cache.SetProxyMaxAge(new TimeSpan(0L));
                    cache.AddValidationCallback(CacheValidateHandler, null);
                }
                else
                {
                    HandleUnauthorizedRequest(filterContext);
                }
            }
        }

All that is happening in the method is that in the filterContext if AllowAnonymous attribute is not defined then AuthorizeCore method would get called otherwise the otherwise the method execution would get skipped.

This implementation is there for a reason. Let us say you have a controller which has the Authorize attribute applied. So by default all the action methods can be executed by Authorized Users only. But if we want to exclude some of the methods from Authorization we need to provide the AllowAnonymous attribute on the action method that needs no authorization.

Let know now go through the AuthorizeCore method and look into the implementation.

protected virtual bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException("httpContext");
            }

            IPrincipal user = httpContext.User;
            if (!user.Identity.IsAuthenticated)
            {
                return false;
            }

            if (_usersSplit.Length != 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
            {
                return false;
            }

            if (_rolesSplit.Length != 0 && !_rolesSplit.Any(user.IsInRole))
            {
                return false;
            }

            return true;
        }

This method first of all checks for the User Identity present in the HttpContext. This method does not care about anything but the Identity of the User in first place.
I have seen most of the people have a wrong impression that the Authorize attribute validates the credentials and generates the FormsAuthenticationCookie.
The FormsAuthenticationCookie is generated by the application developer or the Asp.Net Identity Framework after validating the credentials.
When the FormsAuthenticationCookie is sent to the server the FormsAuthenticationModule validates the Cookie and sets the User Identity in the HttpContext.

In a way we can tell that Authorize attribute checks for Authentication as the first step and then processes the logic further.

In the second step the authorized user names mentioned in the Authorize attribute is validated with the user name in the Identity. If the user in the identity is one of the users mentioned in the attribute the execution continues further.

In the third step the authorized role names mentioned in the Authorize attribute is validated with the role namees in the Identity. If the role in the Identity is one of the roles mentioned in the attribute the execution continues further and the code in the action method is executed.

If any one of the above mentioned checks fails the further execution is terminated and an Unauthorized response if sent back.

Conclusion

In this post we discussed the different processes involved in authenticating a user in a Asp.Net Mvc application. The basic steps involved is the same as that in WebForms Application.
The Authorize attribute plays an important role in validating the

  1. If the User is Authenticated
  2. If the User Name is Authorized
  3. IF the User Role is Authorized

I beleive that learning by going through the source code gives us a clear cut idea of what is happening behind the scene.
The source code of the Authorize attribute clearly explains all it does.