4

I'm writing an ASP.net MVC 5 application using FormsAuthentication. I had everything up and working properly using FormsAuthentication.SetAuthCookie(user.Email, model.RememberMe).

However, I wanted to create a custom ticket so I could store some extra information in the UserData field of the ticket. This is how I'm creating my ticket and storing it in a cookie:

var ticket = new FormsAuthenticationTicket(1, user.Email, DateTime.Now, DateTime.Now.AddMinutes(FormsAuthentication.Timeout.Minutes), model.RememberMe, user.AuthToken);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket) { Domain = FormsAuthentication.CookieDomain, Path = FormsAuthentication.FormsCookiePath, HttpOnly = true, Secure = FormsAuthentication.RequireSSL };
HttpContext.Response.Cookies.Add(cookie);

This creates an encrypted ticket and sends it to the browser. I've verified with developer tools and Fiddler that the ticket is present in the browser and that it is sent back to the server on the subsequent requests.

But authentication is now broken. Also, the cookie is not available in Application_AuthenticateRequest or Application_PostAuthenticateRequest events. When I use the debugger to explore Context.Request.Cookies it is not present in the list.

Oddly enough the cookie does exist if I step back in the pipeline and check it in Application_BeginRequest:

void Application_BeginRequest(object sender, EventArgs e)
{
    // Auth cookie exists in the collection here! Ticket decrypts successfully
    HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie == null)
        return;
    var encTicket = authCookie.Value;
    var ticket = FormsAuthentication.Decrypt(encTicket);
}

void Application_AuthenticateRequest(object sender, EventArgs e)
{
    // Auth cookie missing from the cookies collection here!
    HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie == null)
        return;

    var encTicket = authCookie.Value;
    var ticket = FormsAuthentication.Decrypt(encTicket);
    using (var db = new BadgerContext())
    {
        var user = db.Users.OfType<RegisteredUser>().FirstOrDefault(x => x.UserName == ticket.Name);
        if (ticket.UserData != user.AuthToken)
        {
            FormsAuthentication.SignOut();
            Response.Redirect(FormsAuthentication.DefaultUrl);
        }
    }
}

So it appears that something is stripping my custom FormsAuthenticationTicket out of the cookies after BeginRequest but before AuthenticateRequest. Unfortunately, this breaks authentication altogether on the site.

Any ideas what is causing this behavior when I create a custom ticket? Am I doing something wrong with my cookie creation?

4
  • Possibly need to set cookie.Expires where you're creating the cookie. I wouldn't think this would be necessary assuming we're talking a single browser session but that's the only thing jumping out at me. Commented Jun 13, 2014 at 4:46
  • 3
    What is the value of FormsAuthentication.Timeout.Minutes? The cookie won't exist in the AuthenticateRequest unless it's verified. Make sure the cookie isn't expiring early. Commented Jun 13, 2014 at 4:47
  • Also, while not at all satisfying, if you can get the cookie in BeginRequest, you could potentially use Context.Items to store information for use later in the pipeline. Commented Jun 13, 2014 at 4:48
  • Rowan, I stepped through the code for creating the ticket and FormsAuthentication.Timeout.Minutes was 0, leading to immediate expiration of the ticket. I had to use FormsAuthentication.Timeout.TotalMinutes instead and everything started working properly again. Add as an answer and I will accept. Commented Jun 13, 2014 at 5:35

2 Answers 2

7

Check in the .config file the inside the system.web node, the httpRuntime tag.

<httpRuntime targetFramework="4.5" />

as same as main web site

Sign up to request clarification or add additional context in comments.

1 Comment

This actually fixed the issue for me. Ticket was not expired but still wasn't in collection. After making sure that both of my projects had this in the web.config it worked! Thank you very much!
0

Rowan suggested I look at the value for FormsAuthentication.Timeout.Minutes. After investigation, this value always came back as 0. This led to an immediate expiration of the ticket. I had to use FormsAuthentication.Timeout.TotalMinutes instead and everything started working properly

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.