3
votes

Im building a website with the new ASP.NET MVC3 framework and using FormsAuth. for securing the website. I'm storing the role of a user in the UserData property of the FormsAuthenticationTicket, (setting the cookie manually), I then call the encrypt method on the ticket before adding it to the cookie(see below a Standard ticket sniplet).

if (Validate(model.UserName, model.Password))
                {                     
                    FormsAuthenticationTicket authTicket =  new FormsAuthenticationTicket(1,
                            model.UserName,
                            DateTime.Now,
                            DateTime.Now.AddMinutes(30),
                            false,
                            UserType.Administrator.ToString());
                    string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
                    HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
                    Response.Cookies.Add(faCookie);   
                    return RedirectToAction("startpage", "mycontroller");
                }
            }     

Now I've made a custom AuthorizeAttribute thats able to check if the user is 1. authenticated and 2. has the admin role (from the ticket). (below) The AuthorizeCore method of this derived class will be called when an action takes places in a class that has the attribute annotion.

protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException("httpContext");
            }
            IPrincipal user = httpContext.User;
            if (!user.Identity.IsAuthenticated)
            {
                return false;
            }
            string cookieName = FormsAuthentication.FormsCookieName;
            HttpCookie authCookie = httpContext.Request.Cookies[cookieName];
            if (authCookie == null)
                return false;

            FormsAuthenticationTicket authTicket =       FormsAuthentication.Decrypt(authCookie.Value);
            if (authTicket.UserData != UserType.Administrator.ToString())
                return false;
            return true;

So here's where im getting confused.

When I follow the code being executed (with valid credentials, in debug), and check the values of the variables made on each line, the encryptedTicket encrypts just fine before adding it to the reponsecookie.

But when I then check the AuthorizeCore method when the controller (of the index page) is being called, the parameter its getting, the HttpContext, contains the ticket with everything unencrypted, so there is no need to decrypt the ticket anymore when reading the cookie.

Why do I see the ticket succesfully being encrypted in the logon controller where I send it back to the client, but then when I receive the httpcontext in the AuthorizeAdministrator class its all unencrypted again.

Sorry for the long question/story, there's probably a simple and short answer for it. Hope my story is clear.

Thanks.

1
Why not use User Roles to store the role, instead of writing it yourself and putting it in the UserData field?John Gibb

1 Answers

3
votes

Forms auth needs to decrypt the cookie early in the page processing pipeline, to determine if the user is authorized -- that's when it fills in the details for User.Identity, etc.