Cookie expiration date not working C# - c#

I'm setting a cookie like so:
protected void SetCookie(bool value, int expiration)
{
var cookie = Response.Cookies[COOKIE_NAME] ?? new HttpCookie(COOKIE_NAME);
cookie.Value = value.ToString();
cookie.Expires = DateTime.UtcNow.AddDays(expiration);
Response.Cookies.Set(cookie);
}
In the SetCookie function, when I inspect the cookie on the last line, the Expiration is set to tomorrow's date.
However, when I retrieve this cookie on the next page load:
var cookie = Request.Cookies[COOKIE_NAME];
the cookie exists, but the expiration date is the default date value of 1/1/0001 12:00:00 AM

I believe the expiration is a client-side thing. The browser should send any not-expired cookies, but does not send the expiration date (only name and value). I think you should re-set and refresh the expiration on each request.
This was the first format reference I found: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cookie
If for whatever reason you need to retrieve the expiration data server side, I would include it in the cookie contents or set a secondary cookie to contain that information.

Related

How do I set cookie expiration to session in C#

I am creating a website, and I'm not sure how to use sessions with cookies.
When sessions timeout, I want to show the username and time of the user; for e.g., username stored in cookies and session. When sessions timeout the username must be retrived from the cookies.
Lets put things in perspective first.
A session is the session a user is experiencing when he is using the website.
How it works is basically a user starts a session with the web server, the web server then gives it a key of the session and sets a timeout for the session which are stored as a cookie.
Since this process is automatic and you can only configure it in web.config (unless you are asp.net core vNext, which I doubt) with sessionState https://msdn.microsoft.com/en-us/library/h6bb9cz9%28v=vs.80%29.aspx
A normal HttpCookie on another hand is something you set on your Response object and can give it a specific expiration date like this:
HttpCookie myCookie = new HttpCookie("MyTestCookie");
DateTime now = DateTime.Now;
// Set the cookie value.
myCookie.Value = now.ToString();
// Set the cookie expiration date.
myCookie.Expires = now.AddMinutes(1);
// Add the cookie.
Response.Cookies.Add(myCookie);
Which suits your needs more likely.
If you want more information about sessions expiration I'd also suggest you check out http://www.hanselman.com/blog/TroubleshootingExpiredASPNETSessionStateAndYourOptions.aspx

FormsAuthenticationTicket expiration

I have been searching the web and found many odd answers and i've tried almost all of them.
My problem is this. My login page contains:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(min), persistCookie, userid.ToString());
string encTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
cookie.Expires = ticket.Expiration;
Response.Cookies.Add(cookie);
FormsAuthentication.RedirectFromLoginPage(userName, persistCookie);
Now the min value is per user based and can be set individually, so is persistCookie.
After what i understand this code should result in the possibillity of overriding the default values in web.config. Which should be 30 minutes.
<authentication mode="Forms">
<forms loginUrl="~/Default/default.aspx" defaultUrl="~/User/UserMain.aspx"/>
</authentication>
min is currenlty set to 120, and persistCookie is set too true. When i log in i get timeout at 30 minutes. (Not session, so somewhere expiration date is set, because if it was not set the cookie should be session based, also i do not get 120 minutes which is kind of the deal here)
My question, for simplifying it, is how do i get the value 'min' to be the expiry date of the cookie?
This might turn out too be a simple thing but i am currently totally stuck so any help would be appriciated.
EDIT:
I changed the login logic to this:
FormsAuthenticationTicket fat = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(min), persistCookie, userid.ToString());
string encTicket = FormsAuthentication.Encrypt(fat);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket) { Expires = fat.Expiration });
Response.Redirect(FormsAuthentication.GetRedirectUrl(userName, false));
And now it works. But i cant seem to figure out why this would work, and not the previous one.
Ticket creation is the same, the only difference is that i add Expires property of the HttpCookie when creating the HttpCookie, not after the object is made.
If anybody has a good explanation i am all ears! :)
The problem with your code is that you're calling RedirectFromLoginPage, which will create the forms authentication cookie, overwriting the cookie you've just created:
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
cookie.Expires = ticket.Expiration;
Response.Cookies.Add(cookie);
FormsAuthentication.RedirectFromLoginPage(userName, persistCookie); <-- creates a new cookie
The cookie created by RedirectFromLoginPage will of course have the default timeout taken from configuration.
Your second version is the way to go.
I think you don't understand the difference between cookie expiration and ticket expiration dates - ticket can be considered as expired even if the cookie it is being stored in is still valid. The 4th param of FormsAuthenticationTicket constructor is responsible for the ticket expiration date.
So, to answer your question, you need to manually set expiration date of your cookie or make it long enough to exceed expiration date of your authentication ticket.

c# Asp.net getting Cookie expiration time set in javascript always returns 01.01.0001

I use a javascript function to store the cookie:
createCookie("teaser", "teaser", 7);
function createCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toGMTString();
}
document.cookie = name + "=" + value + expires + "; path=/";
return value;
}
And when I check the cookies in my browser the cookie expiration of teaser is correctly set:
25. oktober 2011 16:12:17
But when in C# i go to get the value, the expiration date is set to 01.01.0001.
var cookie = Request.Cookies["teaser"];
if (cookie != null && teaserList.Count() > 0)
{
cookie.Expires is 01.01.0001
Any clue?
Egghead says that:
The browser is responsible for managing cookies, and the cookie's
expiration time and date help the browser manage its store of cookies.
Therefore, although you can read the name and value of a cookie, you
cannot read the cookie's expiration date and time. When the browser
sends cookie information to the server, the browser does not include
the expiration information. (The cookie's Expires property always
returns a date-time value of zero.) If you are concerned about the
expiration date of a cookie, you must reset it.
The browser does not transmit the expiration date of a cookie to servers, this is as per HTTP specification.
Browsers only send the cookie name and value only.
The Expires property on the cookie object is only used when setting expiration date on a cookie that is going to be written in a response, not read in a request.
When reading the cookie is Expires property value is always going to be null. You can see this for yourself by examining the HTTP headers. If you really want to read the expire value of a cookie, try writing it in the value itself, or using another cookie with the value of the expiration date (you will need to keep them in sync yourself).

How to remove all expired cookie from CookieCollection?

How to remove all expired cookie from a CookieCollection ?
Try this.
var cookies = Request.Cookies;
foreach (HttpCookie cookie in cookies)
{
if (cookie.Expires < DateTime.Now)
{
Request.Cookies.Remove(cookie.Name);
}
}
Please note the excerpt from MSDN,
Calling the Remove method of the Cookies collection removes the cookie
from the collection on the server side, so the cookie will not be sent
to the client. However, the method does not remove the cookie from the
client if it already exists there.
You cannot directly delete a cookie on a user's computer. However, you can direct the user's browser to delete the cookie by setting the cookie's expiration date to a past date. The next time a user makes a request to a page within the domain or path that set the cookie, the browser will determine that the cookie has expired and remove it.
if (Request.Cookies["UserSettings"] != null)
{
HttpCookie myCookie = new HttpCookie("UserSettings");
myCookie.Expires = DateTime.Now.AddDays(-1);//add -1 days
Response.Cookies.Add(myCookie);
}
The way you remove a cookie is to change it expire date to some thing that has already passed.. but a expired cookie should never be sent from the browser in the first case...

Does Decrypting a cookie convert it to local time?

I have my own asp.net cookie created like this:
var authTicket = new FormsAuthenticationTicket(
version,
userName,
DateTime.UtcNow,
DateTime.UtcNow.AddMinutes(30),
createPersistentCookie,
userData,
"/");
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
As you can see everything is in UTC time.
When I decrypt it:
var cookie = HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);
if (cookie != null)
{
var ticket = FormsAuthentication.Decrypt(cookie.Value);
return ticket.Expiration.Ticks;
}
else
{
return 0;
}
It returns local time. So, does it get converted automatically or is it something else? If so how can I get it back to UTC time?
From MSDN:
FormsAuthenticationTicket.Expiration Property
Gets the local date and time at which the forms-authentication ticket expires.
You can use the DateTime.ToUniversalTime method to convert a DateTime to UTC:
return ticket.Expiration.ToUniversalTime().Ticks;
As you've seen, once the FormsAuthenticationTicket has been serialized to a cookie and deserialized, the Expiration and Issue times will always be local.
The Remarks section in MSDN says "If the FormsAuthenticationTicket was created using a constructor that takes an expiration parameter, the Expiration property returns the value supplied to the expiration parameter.". Hence if you pass UTC, you will get back UTC until the ticket has been serialized/deserialized, after which it will be converted to local.
If you supply issueDate and expiration to the constructor, they should normally be in local time. However no attempt is made to convert them to local time - probably the reason for this is for backwards compatibility with .NET 1.x.
With .NET 1.x the DateTime struct did not have a "Kind" property, so there was no way to tell it the caller supplied UTC or local time - it was just assumed to be local.
Therefore I suggest you change your code to pass local time to the FormsAuthenticationTicket constructor, though it does expose you to this bug recorded on Microsoft Connect.

Categories