34

Asp.net MVC2 does redirect to login page with response 302 when authenticated user has no rights.

I would like to split into two actions

  1. If user is not authenticated then do what it does, redirect to login page.
  2. If user is authenticated but has no required rights then return appropriate http status code and show no rights dude page.

Is there any way to do it? Or am I doing something wrong with authorize and form authentication? Only way I can think of is by writing custom authorize attribute, which I want to avoid.

1
  • 2
    haha "no rights dude" page... lol Commented Dec 16, 2010 at 4:43

5 Answers 5

19

You could write custom filter attribute like this:

public class CustomAuthorizeAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.User.Identity == null || !filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                filterContext.Result = new RedirectResult(System.Web.Security.FormsAuthentication.LoginUrl + "?returnUrl=" +
                filterContext.HttpContext.Server.UrlEncode(filterContext.HttpContext.Request.RawUrl));
            }

            //Check user right here
            if (userNotRight)
            {
                filterContext.HttpContext.Response.StatusCode = 302;
                filterContext.Result = new HttpUnauthorizedResult();
            }
        }
    }

And use it in controller:

[CustomAuthorize]
public class HomeController : Controller
{

}
Sign up to request clarification or add additional context in comments.

4 Comments

You should use AuthorizeAttribute instead of ActionFilterAttribute for the purpose of Authorization.
@ReinierDG so, how to implement it with AuthorizeAttribute ?
This appears to fail if the attribute is on the class and the action in question has the AllowAnonymous
9

You could write a custom authorize attribute and in the AuthorizeCore method if the user is not authenticated return a HttpUnauthorizedResult and if he is authenticated but not in roles perform some other action you would like. Note that if you return 401 status code the FormsAuthentication framework will eventually redirect with 302 to the login page.

2 Comments

But... you can only return a bool from AuthorizeCore. You must override OnAuthorization to return an ActionResult
@EduardoMolteni, you could override the HandleUnauthorizedRequest method in order to return the result you want.
7

As suggested in Customizing authorization in ASP.NET MVC, you could subclass the AuthorizeAttribute to intercept the authenticated-but-unauthorized scenario and replace the result with a redirect.

1 Comment

This's better especially for authorize the cached results.
7

Implement a custom AuthorizeAttribute and add the following override. The basics is to check if user is authenticated but not authorized and then redirect to you own "Access Denied" page. Hope this helps!

public override void OnAuthorization(AuthorizationContext filterContext) 
{
    base.OnAuthorization(filterContext);

    // Check if user is authenticated and if this action requires authorization
    if (filterContext.HttpContext.User.Identity.IsAuthenticated
        && filterContext.ActionDescriptor.IsDefined(typeof(AuthorizeAttribute), true)
        || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AuthorizeAttribute), true))
    {
        List<object> attributes = new List<object>(filterContext.ActionDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true));
        attributes.AddRange(filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true));

        // Check all authorzation attributes
        foreach (var attribute in attributes)
        {
            var authAttribute = attribute as AuthorizeAttribute;
            if (authAttribute != null)
            {
                if (!filterContext.HttpContext.User.IsInRole(authAttribute.Roles))
                {
                    // User is not authorized so redirect to our access denied error page
                    filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary 
                            {
                                { "area", "" },
                                { "controller", "Error" },
                                { "action", "AccessDenied" }
                            });
                    break;
                }
            }
        }
    }
}

1 Comment

Add this .... if (authAttribute != null && !string.IsNullOrEmpty(authAttribute.Roles))
3

Similar to solutions suggested by @hellangle and @Andreas, I used the following code to solve this problem:

public class CustomizedAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var userAuthInfo = GetUserAuthInfo();

        if (!userAuthInfo.IsAuthenticated())
        {
            filterContext.Result = new RedirectResult(UrlToYourLoginPage);
            return;
        }

        if (!userAuthInfo.IsAuthorized())
        {
            var result = new ViewResult {ViewName = "UnAuthorized"};
            result.ViewBag.Message = "Sorry! You are not authorized to do this!";
            filterContext.Result = result;
        }
    }
}

Of course, you need to implement the user authorization information class and related methods (GetUserAuthInfo, IsAuthenticated, IsAuthorized) according to your specific needs. Also a View named 'UnAuthorized' should be put to somewhere the MVC engine can find. Then it can be used on a controller class (pointed out in @hellangle's answer) or a action method:

[CustomizedAuthorizeAttribute]
public class TargetController : Controller
{
    [CustomizedAuthorizeAttribute]
    public ActionResult TargetAction()
    {
        // Your Code
    }

}

In order to provide different access control strategy for various controller classes and action methods, implements a constructor for CustomizedAuthorizeAttribute class which accepts parameter(s) representing access control information and then Instantiate CustomizedAuthorizeAttribute class accordingly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.