Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is onAuthorization executing before authentication?

I'm trying to do some custom authorization so I created a controller overriding the OnAuthorization method. I also applied the Authorize attribute to this controller. The question is why is the OnAuthorization method called BEFORE the basic forms authentication process?

I would like to authorize the user after he is authenticated. Am I missing something?

Here is the code:

[Authorize]
    public class AuthorizationController : Controller
    {
        protected override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);

            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            List<string> allowedControllers = new List<string>() { "SecurityController" };
            List<string> allowedActions = new List<string>() { "Index" };

            string controllerName = filterContext.Controller.GetType().Name;
            string actionName = filterContext.ActionDescriptor.ActionName;

            if (!allowedControllers.Contains(controllerName)
            || !allowedActions.Contains(actionName))
            {
                filterContext.Result = View("UnauthorizedAccess");
            }
        }
    }

The controller that I tested with is something like:

public class SecurityController : AuthorizationController
{

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult AnotherIndex()
    {
        return View();
    }
}
like image 949
misha Avatar asked Feb 20 '12 18:02

misha


People also ask

How do you override OnAuthorization?

Right-click on the solution and add a new class. Enter the class name and click on Add. Next Inherite Attribute, IAuthorizationFilter to CustomAuthorization class which has overridden the OnAuthorization method. The OnAuthorization Method has the AuthorizationFilterContext parameter.

How does the Authorize attribute work?

Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action. We can apply the filter globally, at the controller level, or at the level of individual actions.

How does authorization work in net core?

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.

When should we use Authorize attribute?

This attribute is useful when you want to use the Authorize attribute on a controller to protect all of the actions inside, but then there is this single action or one or two actions that you want to unprotect and allow anonymous users to reach that specific action.


2 Answers

One of the first things the AuthorizeAttribute does is check to see if the user is authenticated. If they are not then that is when a redirect to the login page will be issued.

The AuthorizeAttribute basically wraps the authentication check in with the authorization piece:

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

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

When you use the AuthorizeAttribute with no roles/users as you do in your example ([Authorize]), it is basically just checking to make sure the user is authenticated in this case.

I would probably change your code to override the AuthorizeAttribute instead of doing this code in your controller. You can do the following:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        filterContext.Result = CreateResult(filterContext);
    }

    protected ActionResult CreateResult(AuthorizationContext filterContext)
    {
        var controllerContext = new ControllerContext(filterContext.RequestContext, filterContext.Controller);
        var controller = (string)filterContext.RouteData.Values["controller"];
        var action = (string)filterContext.RouteData.Values["action"];
        // any custom model here
        var model = new UnauthorizedModel(); 

        // custom logic to determine proper view here - i'm just hardcoding it
        var viewName = "~/Views/Shared/Unauthorized.cshtml"; 

        return new ViewResult
        {
            ViewName = viewName,
            ViewData = new ViewDataDictionary<UnauthorizedModel>(model)
        };
    }
}
like image 135
Dismissile Avatar answered Sep 19 '22 09:09

Dismissile


Following is a sample for Custom Authorization Attribute.

 public class AuthLogAttribute:AuthorizeAttribute
    {

        public string View { get; set; }

        public AuthLogAttribute()
        {
            View = "AuthorizeFailed";
        }
        public override void OnAuthorization(AuthorizationContext filterContext)

        {
            base.OnAuthorization(filterContext);
            IsUserAuthorized(filterContext);
        }

        private void IsUserAuthorized(AuthorizationContext filterContext)
        {
            // If the Result returns null then the user is Authorized 
            if(filterContext.Result ==null)
                return;

            //If the user is Un-Authorized then Navigate to Auth Failed View 
            if(filterContext.HttpContext.User.Identity.IsAuthenticated)

            {
                var vr = new ViewResult();
                vr.ViewName = View;

                ViewDataDictionary dict = new ViewDataDictionary();
                dict.Add("Message", "Sorry you are not Authorized to Perform this Action");
                vr.ViewData = dict;

                var result = vr;
                filterContext.Result = vr;
            }

        }
    }

Your Controller will be like following,

 [AuthLog(Roles ="Manager")]     
        public ActionResult Create()
        {
            var product = new Product();
            return View(product);
        }

Finally create new Shared view Call "AuthorizeFailed".

like image 42
Manoj Weerasooriya Avatar answered Sep 21 '22 09:09

Manoj Weerasooriya