57

Using FormsAuthentication we write code like this:

 if (IsValidUser())
 {
      FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
      FormsAuthentication.RedirectFromLoginPage(userName, createPersistentCookie); 
 }
  1. How can I manually create a authentication cookie instead of writing FormsAuthentication.SetAuthCookie(userName, createPersistentCookie)?

  2. How can I store a redirect URL from the login page in a string variable instead of writing FormsAuthentication.RedirectFromLoginPage(userName, createPersistentCookie)?

Jay
  • 10,200
  • 4
  • 28
  • 36
Thomas
  • 33,544
  • 126
  • 357
  • 626

2 Answers2

95

Here you go. ASP.NET takes care of this for you when you use the higher level methods built into FormsAuthentication, but at the low level this is required to create an authentication cookie.

if (Membership.ValidateUser(username, password))
{  
  // sometimes used to persist user roles
  string userData = string.Join("|",GetCustomUserRoles());

  FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
    1,                                     // ticket version
    username,                              // authenticated username
    DateTime.Now,                          // issueDate
    DateTime.Now.AddMinutes(30),           // expiryDate
    isPersistent,                          // true to persist across browser sessions
    userData,                              // can be used to store additional user data
    FormsAuthentication.FormsCookiePath);  // the path for the cookie

  // Encrypt the ticket using the machine key
  string encryptedTicket = FormsAuthentication.Encrypt(ticket);

  // Add the cookie to the request to save it
  HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
  cookie.HttpOnly = true; 
  Response.Cookies.Add(cookie);

  // Your redirect logic
  Response.Redirect(FormsAuthentication.GetRedirectUrl(username, isPersistent));
}

I'm not sure why you would want to do something custom here. If you want to change the implementation of where user data is stored and how users authenticate then it's best practice to create a custom MembershipProvider. Rolling your own solution and messing with the authentication cookie means a high probability of introducing security holes in your software.

I don't understand your part 2. You only need to call FormsAuthentication.GetRedirectUrl if you want to return users to the page they were trying to access when they got bounced to login. If not do whatever you want here, redirect to a url stored in the configuration if you want.

To read the FormsAuthentication cookie, normally you would hook the AuthenticateRequest event in a HttpModule or the Global.asax and set up the user IPrinciple context.

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
    if(authCookie != null)
    {
        //Extract the forms authentication cookie
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);

        // If caching roles in userData field then extract
        string[] roles = authTicket.UserData.Split(new char[]{'|'});

        // Create the IIdentity instance
        IIdentity id = new FormsIdentity( authTicket );

        // Create the IPrinciple instance
        IPrincipal principal = new GenericPrincipal(id, roles);

        // Set the context user 
        Context.User = principal;
    }
}
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
TheCodeKing
  • 19,064
  • 3
  • 47
  • 70
  • ur answer helps me...can u please what code i need to write to read the content of authentication cookie after authentication. FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); SetAuthCookie create a authentication cookie and i need to write the content of that cookie from server side? can u help please. thnx. :) – Thomas Aug 28 '11 at 09:22
  • can we create a form authentication cookie from client side using jquery? – Thomas Aug 28 '11 at 09:29
  • 3
    I've updated to show also how you can also read the cookie. No you can't set this from client-side as it would be a security risk and you wouldn't be able to perform the encryption which requires server-side keys. The auth cookie should always be HttpOnly. The only way would be to make an AJAX request and let the cookie be set server-side, in which case you need to ensure you are passing any credentials over SSL. – TheCodeKing Aug 28 '11 at 11:24
  • thanks for ur code....i need one info like that ticket version will be 1 always...or it can any guid also? normally what kind of data is store as user data? – Thomas Aug 28 '11 at 18:22
  • UserData is available for implementations to use how they wish, it's just a space field saved to the cookie for custom content. It's commonly used to cache a list of Roles that the user belongs to in order to optimise lookups (happens only once on authenticate rather than each request). Version is an int. Again it's up to your implementation to use this how it sees fit. It can be used to upgrade a user cookie if the implementation changes. – TheCodeKing Aug 28 '11 at 18:33
  • @TheCodeKing: How are you setting the `HttpOnly` flag here? – escist Jul 10 '12 at 09:15
  • 1
    You can set HttpOnly on the cookie instance before it's saved. Updated to reflect best practice :) – TheCodeKing Jul 10 '12 at 12:16
  • 1
    This was a big help, thanks. The only change I would make would be to get the expiryDate timeout minutes from the web.config. Change DateTime.Now.AddMinutes(30) to DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes) – LawMan Feb 19 '15 at 18:14
  • I like LawMan's code to add minutes from the FormsAuthentication, but adding minutes from a TimeSpan's minutes is extra needless conversion. We can use this instead: `DateTime.Now.Add(FormsAuthentication.Timeout)`. But it's not any big deal, either way. And no harm done with converting to minutes and back, just a few extra cycles of CPU usage. – Shawn Kovac Feb 23 '16 at 17:02
-8

Answer Update on number of down votes casted for this post, Properway of creating a cookie with user information as follows,

Cookie validation on page load of login page,

if (HttpContext.Current.User.Identity.IsAuthenticated)

Cookie creation during authenticated user Login,

 FormsAuthentication.SetAuthCookie(txtUserName.Text.Trim(), true);
 FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
    1,
    txtUserName.Text.Trim(), 
    DateTime.Now,
   (chkRemember.Checked) ? DateTime.Now.AddHours(6) : DateTime.Now.AddHours(2),// Specify timelimit as required
   true,
   string.Empty,                                                
   FormsAuthentication.FormsCookiePath);  
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
cookie.Expires = (chkRemember.Checked) ? DateTime.Now.AddHours(6) : DateTime.Now.AddHours(2);
cookie.HttpOnly = true;
Response.Cookies.Add(cookie);

Below is a Down voted answer - Reason adding an encrypted password in a cookie.

the other way of creating a cookie,

HttpCookie toolCookie = new HttpCookie("xyz");
toolCookie["UserName"] = userName;
toolCookie["Password"] = StringCipher.Encrypt(password, "#!");
toolCookie.Expires = DateTime.Now.AddMinutes(chkRemember.Checked ? 30 : -30);
Request.Cookies.Add(toolCookie);

Reference

Get the Existing cookie details

HttpCookie user = Request.Cookies["xyz"];
if(user != null)
 {
  string username = user["UserName"];
  string password = user["Password"] != null ? StringCipher.Decrypt(user["Password"], "#!")
 }

here Datasecurity is a static class.

Encrypt and Decrypt function Encrypt & Decrypt

Pranesh Janarthanan
  • 1,134
  • 17
  • 26