misha
misha

Reputation: 2889

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();
    }
}

Upvotes: 15

Views: 39491

Answers (3)

Manoj Weerasooriya
Manoj Weerasooriya

Reputation: 639

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".

Upvotes: 2

lalan kumar
lalan kumar

Reputation: 1

public override void OnAuthorization(AuthorizationContext filterContext)
{
    base.OnAuthorization(filterContext);
    bool flag = false;
    string UserId;
    string[] AssignedRights = null;

    //Check if Http Context Contains User Name
    if (HttpContext.Current.User.Identity.Name != null && HttpContext.Current.User.Identity.Name != string.Empty)
    {
        //Get User Id from HttpContext
        UserId = HttpContext.Current.User.Identity.Name;
        RoleRepository roleRepository = new RoleRepository();
        AssignedRights = roleRepository.GetRolesByUser(Convert.ToInt32(UserId));
        flag = IsUserAuthorized(filterContext, flag, AssignedRights);

        if (flag == false)
       {

           filterContext.Result = new HttpUnauthorizedResult();
        }
    }

}

Upvotes: -2

Dismissile
Dismissile

Reputation: 33071

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)
        };
    }
}

Upvotes: 17

Related Questions