tags:

views:

119

answers:

2

How can I include a user regardless of his role, dependent on a matching userID, and not always same user:

 [Authorize(Roles="Group1") AND userID=uniqueID]
+1  A: 

You could write a custom Authorize filter (implement IAuthorizationFilter)

Your custom Authorize filter could take the userId as a parameter.

Something like

public class 
    YourAuthorizeFilterAttribute : AuthorizeAttribute,  IAuthorizationFilter
{
    public string UserId { get; set; }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if(filterContext.HttpContext.User.Identity.Name != UserId && 
            !filterContext.HttpContext.User.IsInRole(base.Roles))
        {
            filterContext.Result = new RedirectResult("/Account/LogOn");
        }
    }
}

Then use your own filter like so

[YourAuthorizeFilter(UserId = "theuser", Roles ="Group1")]

Kindness,

Dan

Daniel Elliott
You'd risk leaving the user in the role on failure. I'd prefer a solution without that risk.
tvanfosson
Agreed altered a bit
Daniel Elliott
+4  A: 

You won't be able to do this with the default AuthorizeAttribute. You will need to extend AuthorizeAttribute with a custom class that adds the user behavior. Typically it uses named users, but you could provide an alternative. Normally if you supply both Users and Roles, it will require that the user be in the list of users and have one of the indicated roles.

public class UserOrRoleAuthorizeAttribute : AuthorizeAttribute
{
    public int? SuperUserID { get; set; }

    protected override bool AuthorizeCore( HttpContextBase httpContext )
    {
         if (base.AuthorizeCore( httpContext ))
         {
             var userid == ...get id of current user from db...
             return userid == this.SuperUserID;
         }
         return false;
    }
}

Used as:

[UserOrRoleAuthorize(Roles="Admin",SuperUserID=15)]
public ActionResult SomeAction() ...

Note that you could also add in some way of specifing where to look for the id for this action, .i.e.,

 Table="Admins",Column="AdminID",MatchProperty="Company",MatchParameter="company"

then put some code into the attribute to look up the value in the property table and column and comparing it to the specified RouteValue entry instead of hard-coding it.

tvanfosson
the superUserID will be dependent on the value of the posted parameters.
zsharp
Then add something like the properties I listed in the alternative to specify what parameter(s) in the route values to use to lookup the correct user. These would be the keys in the RouteValueDictionary. Design the logic in your custom attribute to extract the id from the proper table and compare it to the current user.
tvanfosson
where exactly is the RouteValueDicitonary?
zsharp
and shouldnt it be "override" instead of "virtual"
zsharp
Absolutely correct. Also, RouteValueDictionary is used internally in the standard extensions to take an anonymous object with properties and convert it into a Dictionary of key/value pairs. It's in the System.Web.Routing namespace. If you look at the signatures of the ActionLink methods they take a Dictionary of this type.
tvanfosson
It worked for the userID but excluded the "Roles".
zsharp
The base OnAuthorize method should return true if the user is in one of the acceptable roles. This would skip the check for user id. If you need to check both then you'd need change the sense of the check so that only if the user is in the role will it then go on to check the user id.
tvanfosson
I think you should have "return true" instead of "return false".
zsharp
Returning true means that they are authorized. Surely if they aren't in a role and not the authorized user, they aren't authorized so it should return false.
tvanfosson
maybe im wrong, but the way you have it here it seems that if base.authorize core is already true it wont run the second check and so it should stay authorized (ie return true). If base.authorizecore is false it will check the superuser id and return new result.
zsharp
I think I misunderstood your original request. I thought you wanted in a role OR a particular user. I'll rewrite to be in a role AND a particular user.
tvanfosson
no problem. i got the idea. thanks.
zsharp