The user is in the role of "admin", but [Authorize (Roles = "admin")] will not authenticate

I found a great answer to SO describing customizing user user roles , and I did the same in my project. Therefore, in my login service, I have:

public ActionResult Login() { // password authentication stuff omitted here var roles = GetRoles(user.Type); // returns a string eg "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 another 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 log in as a user with the admin role and this works. Then I call / services / doadminstuff - and I get access to it, although when I set a breakpoint in Global.asax.cs, I see that my roles include "admin". If I comment on the first Authorize attribute (with roles) and just use plain Authorize vanilla, then I can access this service.

I need to miss something important here - but where to start looking?

+8
asp.net-mvc
Mar 15 '11 at 16:19
source share
2 answers

I would recommend using the special 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() { ... } 

It is also very important to make sure that an authentication cookie is issued when you log in, because you are returning an XML file. Use FireBug to verify that the authentication cookie was sent correctly when trying to access the /services/doadminstuff .

+15
Mar 15 '11 at 16:25
source share

First, I would change the purpose of the principle:

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

what the ASP.NET documentation looks like.

0
Mar 27 '15 at 13:58
source share



All Articles