User is in role “admin” but [Authorize(Roles=”admin”)] won’t authenticate

I found a great answer on SO describing how to set up custom user roles, and I’ve done the same in my project. So in my Login service I have:

public ActionResult Login() {
  // password authentication stuff omitted here
  var roles = GetRoles(user.Type); // returns a string e.g. "admin,user"
  var authTicket = new FormsAuthenticationTicket(
                    1,
                    userName,
                    DateTime.Now,
                    DateTime.Now.AddMinutes(20), // expiry
                    false,
                    roles,
                    "/");
  var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, 
    FormsAuthentication.Encrypt(authTicket));
  Response.Cookies.Add(cookie);
  return new XmlResult(xmlDoc); // don't worry so much about this - returns XML as ActionResult
}

And in Global.asax.cs, I have (copied verbatim from the other answer):

protected void Application_AuthenticateRequest(Object sender, EventArgs e) {
  var authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
  if (authCookie != null) {
    var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    var roles = authTicket.UserData.Split(new Char[] { ',' });
    var userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
    Context.User = userPrincipal;
  }
}

Then, in my ServicesController class, I have:

[Authorize(Roles = "admin")]
//[Authorize]
public ActionResult DoAdminStuff() {
  ...
}

I login as a user with the “admin” role, and that works. Then I call /services/doadminstuff – and I get access denied, even though when I put a breakpoint in Global.asax.cs, I can see that my roles do include “admin”. If I comment out the first Authorize attribute (with roles) and just use a plain vanilla Authorize, then I can access the service.

I must be missing something critical here – but where to start looking?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I would recommend you use a custom authorize attribute instead of Application_AuthenticateRequest:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        string cookieName = FormsAuthentication.FormsCookieName;

        if (!filterContext.HttpContext.User.Identity.IsAuthenticated ||
            filterContext.HttpContext.Request.Cookies == null ||
            filterContext.HttpContext.Request.Cookies[cookieName] == null
        )
        {
            HandleUnauthorizedRequest(filterContext);
            return;
        }

        var authCookie = filterContext.HttpContext.Request.Cookies[cookieName];
        var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        string[] roles = authTicket.UserData.Split(',');

        var userIdentity = new GenericIdentity(authTicket.Name);
        var userPrincipal = new GenericPrincipal(userIdentity, roles);

        filterContext.HttpContext.User = userPrincipal;
        base.OnAuthorization(filterContext);
    }
}

and then:

[CustomAuthorize(Roles = "admin")]
public ActionResult DoAdminStuff() 
{
    ...
}

Also a very important thing is to ensure that when you login an authentication cookie is emitted because you return an XML file. Use FireBug to inspect whether the authentication cookie is properly sent when you try to access the url /services/doadminstuff.

Method 2

I would change principal assign at first:

Thread.CurrentPrincipal = userPrincipal;
if (HttpContext.Current != null)
{
    HttpContext.Current.User = userPrincipal;
}

as ASP.NET documentation stands.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x