2
votes

I have extended the Authorize attribute to include roles which comes from a cookie. Debugging gives good result, it returns true or false accordingly. However if I first log in with "Admin" Role and then try to go to a controller that requires a User role, the Authorize returns false but still the controller allows access.

protected override bool AuthorizeCore(HttpContextBase httpContext) 
    {


        if (httpContext == null) throw new ArgumentNullException("httpContext"); 

        if (httpContext.User != null)
        {
            if (httpContext.User.Identity.IsAuthenticated)
            {
                if (httpContext.User.Identity is FormsIdentity)
                {
                    FormsIdentity id = httpContext.User.Identity as FormsIdentity;
                    FormsAuthenticationTicket ticket = id.Ticket;
                    string role = ticket.UserData;

                    if (RequiredRole.Contains(role)) return true;
                }
            }
            else 
                return false;

        }
        return false;

    }

Requiredrole is a property of the class.

 [CustomAuthorize(RequiredRole = "Admin", LoginPage = "Club")]
public class UsuarioAdminController : Controller
{

above code for a controller that requires admin role.

[CustomAuthorize(RequiredRole = "User", LoginPage = "Club")]
public class HotelController : Controller
{

above code for a controller with User role. Can someone see why if Authorize returns false it allows access? Thanks

The AuthorizeCore Attribute behave as expected, it returns true or false; however the controller allows access when the AuthorizeCore method returns false.

Yes, there is more code, but I dont think it makes a differnce..here it is.

public class CustomAuthorizeAttribute: AuthorizeAttribute
{
    public string RequiredRole;
    public string LoginPage;

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    {


        if (httpContext == null) throw new ArgumentNullException("httpContext"); 

        if (httpContext.User != null)
        {
            if (httpContext.User.Identity.IsAuthenticated)
            {
                if (httpContext.User.Identity is FormsIdentity)
                {
                    FormsIdentity id = httpContext.User.Identity as FormsIdentity;
                    FormsAuthenticationTicket ticket = id.Ticket;
                    string role = ticket.UserData;

                    if (RequiredRole.Contains(role)) return true;
                }
            }
            else 
                return false;

        }
        return false;

    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {

        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            var routeValues = new RouteValueDictionary();
            if (LoginPage == "Club")
            {
                routeValues["action"] = "Index";
                routeValues["controller"] = LoginPage;
                routeValues["ReturnUrl"] = filterContext.HttpContext.Request.RawUrl;
                filterContext.Result = new RedirectToRouteResult(routeValues);
            }
            else {
                routeValues["area"] = "mobile";
                routeValues["action"] = "login";
                routeValues["controller"] = LoginPage;
                routeValues["ReturnUrl"] = filterContext.HttpContext.Request.RawUrl;
                filterContext.Result = new RedirectToRouteResult(routeValues);
            }
        }

    }

}
1
Put there a breakpoint and check what's happening in AuthorizeCore code, when it's returning false. - David Ferenczy Rogožan
Yes, I did that. It does returns what i need, true or false. But even if it returns false the controller allows access. - Manuel Valle
Oh, I see, sorry, I didn't understand it before. - David Ferenczy Rogožan
Please show the rest of your custom AuthorizeAttribute code. Most likely, you have overridden something else that is causing it not to function. - NightOwl888

1 Answers

1
votes

I found the answer to this particular situation and I am sharing my findings. When a request was properly unauthorized it was handled by the

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)

method. Inside that method I was checking first if the user is not authenticated. For the first request it works properly sending the user to the appropriate log in page, But now if you try to navigate to another page that requires a different role, because you are already authenticated it wont go inside the redirect and will allow access to the control. So by removing the !IsAuthenticated if at the beginning, now all unauthorized request is properly sent to the correct login page...