views:

120

answers:

2

I'm looking at the [Authorize(Roles = "DefaultUser")] available in MVC, but I can't seem to figure out if I can use it with DotNetOpenAuth.

I'm using OpenID as my sole membership provider, but I have a few generic items in a UserProfile table. I don't want anyone except the appropriate user to be able to access the edit controller.

EXAMPLE:
UserID 2 should not be able to access /Users/Edit/1, but they CAN access /Users/Edit/2

A: 

I do not think that [Authorize(Roles = "DefaultUser")] means that people can edit only their own profile. It rather means that everyone in the DefaultUser role can edit profiles... Here is a discussion about it, that is pretty much the same question: http://stackoverflow.com/questions/390930/asp-net-mvc-authorization-using-roles

EDIT: Ok, then your problem is that roles and identity does not work with OpenID? The Authorize thing works only if the HttpContext.Current.User contains the right principal. If you use OpenID this does not happen out of the box, but you have to do something like this in your Global.asax:

void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
{
    HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
        string encTicket = authCookie.Value;
        if (!String.IsNullOrEmpty(encTicket))
        {
            FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(encTicket);
            YourAppIdentity id = new YourAppIdentity(ticket);
            string username = ticket.Name;
            string[] roles = Roles.GetRolesForUser(username);
            GenericPrincipal prin = new GenericPrincipal(id, roles);
            HttpContext.Current.User = prin;
        }
    }
}

where YourAppIdentity should be something that implements IIdentity...

apolka
No I realize that. I probably should have used `[Authorize(Users = "DefaultUser")]` in my example
rockinthesixstring
+1  A: 

Edit/Rewrite for clearer understanding

public class AdvancedAuthorizeAttribute : AuthorizeAttribute
    {
            public string RouteDataValue
            {
                get;
                set;
            }

            protected override bool AuthorizeCore(HttpContextBase httpContext)
            {
                if(base.AuthorizeCore(httpContext))
                {
                    MvcHandler mvcHandler = httpContext.CurrentHandler as MvcHandler;
                    if (mvcHandler != null)
                    {
                        var paramValue = mvcHandler.RequestContext.RouteData.Values[RouteDataValue];
                        if (paramValue != null)
                        {
                            // Inside this IF-statement is where you'll have to customize for your code.

                            //I use the default user from HttpContext
                            string UserPrincipalName = httpContext.User.Identity.Name;
                            // I use email as login name, and here I try to fetch a user from my repository with that email.
                            User userObject = new Repository<User>().GetOne(x => x.Email == UserPrincipalName);
                            // If I find a user, and that user's UserID is equal to the value in paramValue, it's Ok! Otherwise, not.
                            return (userObject != null && userObject.UserID.ToString() == paramValue.ToString());
                        }
                    }
                }
                return false;
            }
    }

And then, using it:

// Example usage (for instance from UserController)
[AdvancedAuthorize(RouteDataValue="userID")]
public ActionResult Edit(int userID)
{
     // everything as normal
}

[AdvancedAuthorize(RouteDataValue="userEmail")]
public ActionResult Delete(string userEmail)
{
     // everything as normal
}

Of course, for it to work, userID and userEmail in the action examples need to be bound by the modelbinder (the parameters have to exist in the RouteData.Values) for it to work.

Terje
does this get put in `void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)`?
rockinthesixstring
No. You create your UserIDAuthorizeAttribute (or equivalent) which extends AuthorizeAttribute and overrides AuthorizeCore. There, you check if(base.AuthorizeCore(context)) { ...put code above here ... }
Terje
I'm sorry... I really haven't a hot clue.
rockinthesixstring
Updated, - hope it is clearer now.
Terje
nice, thanks!!!
rockinthesixstring

related questions