0

Assume like this is my SampleController action method

public ActionResult AdminView()
{
    return View()
}

If want this controller method to be called if the logged in user belongs to admin role, otherwise this method call should be blocked and the user should get an some custom unauthorized access error page.

In my asp .net mvc web application, when the user logs in, I am storing the user role in a session as a string. And whenever there is a need to validate the user role, I compare the value stored in the session against a constant say "ADMIN_ROLE". But I am writing that piece of code to check for the user role in almost every controller action method and then either return an appropriate view for the user or an unauthorized access page view if the user role is restricted for the controller action method.

I googled and read that we can use something like this.

[Authorize(Roles="admin")]
public ActionResult AdminView()
{
  return View()
}

But I am not sure how the Authorize and the Roles keyword works. How when putting Roles = "Admin", is going to help in checking my user role string stored in the session, or how I can redirect a user to unauthorized page, in case the role does not match the role tagged for the action method.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
SARAVAN
  • 14,571
  • 16
  • 49
  • 70
  • 1
    Is your project MVC 3 or MVC 4? – Andrew Apr 04 '13 at 04:30
  • @Andrew My project is in MVC4 – SARAVAN Apr 04 '13 at 04:31
  • @SARAVAN considering its an MVC 4 project, are you using ASP.NET SimpleMembership API for authentication/authorization or custom implementation? – Adil Apr 04 '13 at 04:32
  • @AdilMughal I am not using membership API. I am writing some custom code that checks if the userrole in session equal "ADMIN" then return the appropriate view or else return unauthorized page. I am writing this in almost every controller action, to first check if the role is valid and then return the page accordingly. – SARAVAN Apr 04 '13 at 04:33
  • @SARAVAN Try doing Roles.getRolesForUser(*pass UserName); I haven't tried that in MVC 4, but if that works then the Authorize line I believe will automatically pull the Role for the current user and you won't need the session variable. Also, delete that line after you try it because you won't need it. – Andrew Apr 04 '13 at 04:40
  • @Andrew, you have the right idea for standard membership, but not for **custom code that checks if the userrole in session equal "ADMIN"**. In this case, SARAVAN must implement a custom auth filter – Dave Alperovich Apr 04 '13 at 04:42
  • @SARAVAN In case of custom, you may need to create your own action filter attribute. See my answer below. – Adil Apr 04 '13 at 05:07

3 Answers3

1

As per comments, if you are using custom authentication/authorization mechanism then you need to implement custom authorize attribute where you can put custom logic to check if user has admin role or not. Something like below:

public class CustomizedAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        //check for role in session variable "ADMIN_ROLE"

    //if not valid user then set
    filterContext.Result = new RedirectResult(URL)
    }
}
Adil
  • 3,248
  • 1
  • 22
  • 27
  • 1
    This is useful and definitely an acceptable answer too. But I thought the one that I accepted in detail is what I was looking for. Thanks for your guidance and suggestion. I really appreciate it. – SARAVAN Apr 04 '13 at 06:03
1

As per my thinking you need to code for authorization.

public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
    private readonly RoleEnum[] _acceptedRoles;

    public AuthorizeAttribute(params RoleEnum[] acceptedroles)
    {
        _acceptedRoles = acceptedroles;
    }

    public AuthorizeAttribute(params bool[] allowAll)
    {
        if (allowAll[0])
            _acceptedRoles = new RoleEnum[] { RoleEnum.Admin, RoleEnum.user};
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (SessionHelper.UserInSession == null)//user not logged in
        {
            FormsAuthentication.SignOut();
            filterContext.Result =
                 new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary {{ "controller", "Home" },
                                             { "action", "Index" },
                                             { "returnUrl",    filterContext.HttpContext.Request.RawUrl } });//send the user to login page with return url
            return;
        }
        if (!_acceptedRoles.Any(acceptedRole => SessionHelper.UserInSession.UserRoles.Any(currentRole => acceptedRole == currentRole.Role)))
            //allow if any of the user roles is among accepted roles. Else redirect to login page
            throw new UnauthorizedAccessException();

    }
}

This is also work for return URL.

Amit
  • 15,217
  • 8
  • 46
  • 68
0

There is a small nice explanation in this link:

http://weblogs.asp.net/jgalloway/archive/2011/04/28/looking-at-how-asp-net-mvc-authorize-interacts-with-asp-net-forms-authorization.aspx

as per this:

ASP.NET MVC includes an [Authorize] attribute, which when placed on any controller actions will forbid unauthorized access. The AuthorizeAttribute allows you to specify a list of roles or users. You can also place the AuthorizeAttribute on a controller, in which case it will apply to all actions in the controller. Attempting to access an action secured by the AuthorizeAttribute when you're not logged in will take you to a standard LogOn screen, with a link to register if you don't already have an account.

How does the [Authorize] attribute redirect me to Log On?

The AuthorizeAttribute is an ActionFilter, which means that it can execute before the associated controller action. The AuthorizeAttribute performs its main work in the OnAuthorization method, which is a standard method defined in the IAuthorizationFilter interface. Checking the MVC source code, we can see that the underlying security check is really just looking at the underlying authentication information held by the ASP.NET context:

IPrincipal user = httpContext.User;

if (!user.Identity.IsAuthenticated)
{
    return false;
}

If the user fails authentication, an HttpUnauthorizedResult ActionResult is returned, which produces an HTTP 401(Unauthorized) status code. If it weren’t for ASP.NET Forms Authentication, an HTTP 401 status code would be sent to the browser, which would show the browser’s default login prompt.

Ken Clark
  • 2,500
  • 15
  • 15
  • Ken, as OP has specified this is custom provider, your answer seems incomplete without explaining custom auth filter... as OP will no doubt need one – Dave Alperovich Apr 04 '13 at 04:36
  • 1
    @kenclark Hi Ken. Thanks for your answer. Your example clearly explains authentication. But I am asking about authorization. In my example I am storing the user role in session, and I want the admin's controller actions to be fired only for users who are admins and it should not fire for users who are in a role say "NORMALUSER". How do I implement such things in ASP .net MVC? – SARAVAN Apr 04 '13 at 04:38