I have a problem with my WebForms project that the session ID is renewed on each request. This problem does not occur on my standard IIS, so I concluded that it's a local issue with my development setup.
For testing, I simply created an .aspx page with the following code:
<%: HttpContext.Current.Session.SessionID %>
As stated, when I refresh this page locally, running Visual Studio 2015 and IIS Express, I get a new session ID with each request. (Debugging, checking the session contents and whatnot all yield the same result.)
What's up with this, you think?
(I've seen claims that the browser link feature could cause similar issues. I don't understand how that could be, but nevertheless tried disabling it, restarting Visual Studio and whatnot, but to no avail.)
I'll be answering my own question this time:
When further examining why the session cookie did not "stick", checking the response headers I suddenly realized that for some reason the server was trying to set the session cookie as "secure":
Set-Cookie:ASP.NET_SessionId=lgkbje1igeprk3u53dsfbvtg; path=/; secure; HttpOnly
While this is not at all a bad thing per se, in my development setup it was unexpected. I did not run the request over https, so consequently the session cookie was dropped.
The culprit in this case, was to be found in the web.config
, where I had:
<httpCookies httpOnlyCookies="true" requireSSL="true" />
This is all slightly embarrassing to me, but I thought it might be of help to someone in the future, the realization that the observed behavior (new session with each request) may come from trying to set the session cookie as "secure" without a secure connection, i.e. https
.
[EDIT] In response to a question in the comments about the ideal setting for different environments:
I don't think you can say there's an "ideal" setting for local, test or staging environment, as that depends entirely on your needs for each environment.
It's perhaps less arbitrary to talk about an "ideal" setting for production environments, or "live" as you say; For ASP.NET, personally I would always use:
<httpCookies httpOnlyCookies="true" requireSSL="true" />
To expand on the subject of security in general, I'd also make sure that the HSTS HTTP header is set. Again, the exact approach to achieve this depends on your context, like what platform your using etc. In an older ASP.NET application, where AFAIK there is no better way, I'd put something in Global.asax
along the lines of:
protected void Application_BeginRequest(Object sender, EventArgs e) {
if(Request.IsLocal)
return;
switch (Request.Url.Scheme) {
case "https":
Response.AddHeader("Strict-Transport-Security", "max-age=300");
break;
case "http":
var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", path);
break;
}
}
Of course, there are other HTTP headers that is relevant for security as well, and other information that you should change the default configuration of your application and web server to NOT reveal. Here are some links on the subject:
Furthermore, I'd look to the machine.config
and set:
<deployment retail="true" />
This setting is supposed to ensure that debug mode is turned off and custom errors is turned on, so you do not accidentally leak things like stack traces and stuff. Here's blog on the topic - another a nice Troy Hunt piece, like the one linked above - old, but still relevant:
OWASP Top 10 for .NET developers part 6: Security Misconfiguration - Troy Hunt