After a few window.open calls my ASP.NET session times out - asp.net

I have an ASP.NET application that uses StateServer session mode with cookieless set to false. In a few places, there is a link that pops up a window to another application (which happens to reside on the same domain, but in a different virtual directory). The following steps give me grief...
Launch popup
Close popup
Launch popup to same app as before with a couple different parameters
Close popup
Next request = session timeout on the "parent" window.
Using cookieless sessions fixes the problem, so somehow my cookie is getting whiped out by the browser. Aside from using cookieless sessions, how can this be resolved? For what it's worth, I am developing/testing with IE8.
EDIT
It seems the problem only occurs when the popup resides on the same domain. If I popup a page elsewhere, there is no problem.

Is it possible the other app (on the same domain) is setting its own cookie, overwriting that of your primary app? Can you use fiddler (or similar tool) to see which cookies are being set by which apps?

Check all instances of your
Session.Clear();
Session.Abandon();
If you aren't using those at all, then its likely the case that your browser windows are set to NOT share sessions between. So the new instance gets a NEW session cookie (since its the same cookie name as the prior one, it could possibly kill the existing session cookie)- as in a play on:
http://geekswithblogs.net/ranganh/archive/2009/04/17/asp.net-session-state-shared-between-ie-tabs-and-ie8.aspx
Ideally track down in which page the Set-Cookie header is coming across. Look then at the request going INTO that response and see if your current ASP.NET_SESSIONID cookie is sent over. (fiddler is indeed the best tool for this)
Anyway - its a start to try.

edit Apparently it's not your cookie name, so...
Perhaps you should have an AJAX call on your master page that pings a service (or generic handler) on your web app to keep the session alive.
JavaScript
window.setInterval(function() {
$.get('ping.ashx?nocache=' + (new Date()).getTime(), function() {
return true;
})
}, 30000);
In the Generic Handler, make sure to add the IRequiresSessionState marker interface.
Perhaps your session cookie names are the same.
In your web.config (for one of the applications) change the session cookie name.
<sessionState
mode="StateServer"
timeout="20"
cookieName="DifferentASP.NET_SessionId"

Related

How to detect if SessionState has expired?

What would be the best way to detect if the SessionState has died in order to send the user to a "Session Expired" page? I've successfully configured the app (in Web.config) to do this when the authentication cookie is gone (there's a setting for that), but so far I haven't found an effective way to do something similar when the SessionState is gone. The app in question holds some data in the Session, and should present the user with a "Session Expired - Please login again" page if any of them is gone.
So far, the only option I can think of doing it in each of the places I access Session, but this is obviously a less than optimal solution.
I remember a similar question. Actually, you don't have many opportunities.
I mean, you can't redirect a user to a page when server fires the SessionEnd event, that you can handle in Global.asax.
However, if you play with the Session object from inside the page you can do something useful... For example, save the session ID in the page's context, or in a hidden field. When you postback, compare the saved ID with your Session ID. If they differ, a new session started, meaning that the old one expired.
Now it's time to redirect the user :)
Hope to have been of help.
Yeah it's tough. :)
There is no real simple/definitive way to do it.
One option is stick a guid/idenfitier in the Session[] collection during Session_Start (global.asax), and then check for this value in Page_Load of your base page (e.g master).
Another option is to check the actual ASPX cookie:
HttpCookie sessionCookie = Request.Cookies["ASP.NET_SessionId"];
If it's null, the session is over.
Why not include the session check on the masterpage? Any of your session variables will return null if the session has expired. So on page_load you can check any of them and carry out the appropriate action i.e. Response.Redirect. However you say in the Web.Config you can check when the authentication cookie is gone, so can you not carry out an action on this?
Another method would be to use a HTTP Module which would intercept each request and decide what to do with it. This would be better than my first method and it'll occur prior to any page processing.
When the client logs in, you give him a session flag, like notexpired and set it to 1.
Then you write a web-module, which on every http request checks if notexired = 1.
If that check throws an exception or is 0, you can deny access or redirect to an error page.
or you can renew the session from the database, should you save sessions into the database.
Incidentially, this also works with AJAX handlers, unlike base-page class hacks.
there are lots of examples on internet to solve your problem (it's quite common)
have a look at
http://geekswithblogs.net/shahed/archive/2007/09/05/115173.aspx
Another way is check the repository sessions values are maintained.
In my case we have a hashtable and we log the session ID then every time we need that session we checked if the value is still there..
That a centralized way to keep your app about the status of your session
Hope this helps/
Check out for this property at the Page_Load event of your desired page:
Dim sessionExpired as Boolean = Context.Session.IsNewSession
For more information, please visit this link.
Notice the "liveliness" of the session state is set by default to 20 min, but this can be easily changed in the web.config of the application with the timeout property:
<system.web>
<!--Set default timeout for session variables (default is 20 minutes, but was changed to 30 minutes-->
<sessionState mode="InProc" cookieless="false" timeout="30" />
</system.web>
Also, please check out at MSDN for the other properties mode and cookieles. It can help to extend the validity of your current business situation.

ASP.NET: Session.SessionID changes between requests

Why does the property SessionID on the Session-object in an ASP.NET-page change between requests?
I have a page like this:
...
<div>
SessionID: <%= SessionID %>
</div>
...
And the output keeps changing every time I hit F5, independent of browser.
This is the reason
When using cookie-based session state, ASP.NET does not allocate storage for session data until the Session object is used. As a result, a new session ID is generated for each page request until the session object is accessed. If your application requires a static session ID for the entire session, you can either implement the Session_Start method in the application's Global.asax file and store data in the Session object to fix the session ID, or you can use code in another part of your application to explicitly store data in the Session object.
http://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.sessionid.aspx
So basically, unless you access your session object on the backend, a new sessionId will be generated with each request
EDIT
This code must be added on the file Global.asax. It adds an entry to the Session object so you fix the session until it expires.
protected void Session_Start(Object sender, EventArgs e)
{
Session["init"] = 0;
}
There is another, more insidious reason, why this may occur even when the Session object has been initialized as demonstrated by Cladudio.
In the Web.config, if there is an <httpCookies> entry that is set to requireSSL="true" but you are not actually using HTTPS: for a specific request, then the session cookie is not sent (or maybe not returned, I'm not sure which) which means that you end up with a brand new session for each request.
I found this one the hard way, spending several hours going back and forth between several commits in my source control, until I found what specific change had broken my application.
In my case I figured out that the session cookie had a domain that included www. prefix, while I was requesting page with no www..
Adding www. to the URL immediately fixed the problem. Later I changed cookie's domain to be set to .mysite.com instead of www.mysite.com.
my problem was that we had this set in web.config
<httpCookies httpOnlyCookies="true" requireSSL="true" />
this means that when debugging in non-SSL (the default), the auth cookie would not get sent back to the server. this would mean that the server would send a new auth cookie (with a new session) for every request back to the client.
the fix is to either set requiressl to false in web.config and true in web.release.config or turn on SSL while debugging:
Using Neville's answer (deleting requireSSL = true, in web.config) and slightly modifying Joel Etherton's code, here is the code that should handle a site that runs in both SSL mode and non SSL mode, depending on the user and the page (I am jumping back into code and haven't tested it on SSL yet, but expect it should work - will be too busy later to get back to this, so here it is:
if (HttpContext.Current.Response.Cookies.Count > 0)
{
foreach (string s in HttpContext.Current.Response.Cookies.AllKeys)
{
if (s == FormsAuthentication.FormsCookieName || s.ToLower() == "asp.net_sessionid")
{
HttpContext.Current.Response.Cookies[s].Secure = HttpContext.Current.Request.IsSecureConnection;
}
}
}
Another possibility that causes the SessionID to change between requests, even when Session_OnStart is defined and/or a Session has been initialized, is that the URL hostname contains an invalid character (such as an underscore). I believe this is IE specific (not verified), but if your URL is, say, http://server_name/app, then IE will block all cookies and your session information will not be accessible between requests.
In fact, each request will spin up a separate session on the server, so if your page contains multiple images, script tags, etc., then each of those GET requests will result in a different session on the server.
Further information: http://support.microsoft.com/kb/316112
My issue was with a Microsoft MediaRoom IPTV application. It turns out that MPF MRML applications don't support cookies; changing to use cookieless sessions in the web.config solved my issue
<sessionState cookieless="true" />
Here's a REALLY old article about it:
Cookieless ASP.NET
in my case it was because I was modifying session after redirecting from a gateway in an external application, so because I was using IP instead on localhost in that page url it was actually considered different website with different sessions.
In summary
pay more attention if you are debugging a hosted application on IIS instead of IIS express and mixing your machine http://Ip and http://localhost in various pages
In my case this was happening a lot in my development and test environments. After trying all of the above solutions without any success I found that I was able to fix this problem by deleting all session cookies. The web developer extension makes this very easy to do. I mostly use Firefox for testing and development, but this also happened while testing in Chrome. The fix also worked in Chrome.
I haven't had to do this yet in the production environment and have not received any reports of people not being able to log in. This also only seemed to happen after making the session cookies to be secure. It never happened in the past when they were not secure.
Update: this only started happening after we changed the session cookie to make it secure. I've determined that the exact issue was caused by there being two or more session cookies in the browser with the same path and domain. The one that was always the problem was the one that had an empty or null value. After deleting that particular cookie the issue was resolved. I've also added code in Global.asax.cs Sessin_Start method to check for this empty cookie and if so set it's expiration date to something in the past.
HttpCookieCollection cookies = Response.Cookies;
for (int i = 0; i < cookies.Count; i++)
{
HttpCookie cookie = cookies.Get(i);
if (cookie != null)
{
if ((cookie.Name == "ASP.NET_SessionId" || cookie.Name == "ASP.NET_SessionID") && String.IsNullOrEmpty(cookie.Value))
{
//Try resetting the expiration date of the session cookie to something in the past and/or deleting it.
//Reset the expiration time of the cookie to one hour, one minute and one second in the past
if (Response.Cookies[cookie.Name] != null)
Response.Cookies[cookie.Name].Expires = DateTime.Today.Subtract(new TimeSpan(1, 1, 1));
}
}
}
This was changing for me beginning with .NET 4.7.2 and it was due to the SameSite property on the session cookie. See here for more info: https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/
The default value changed to "Lax" and started breaking things. I changed it to "None" and things worked as expected.
Be sure that you do not have a session timeout that is very short, and also make sure that if you are using cookie based sessions that you are accepting the session.
The FireFox webDeveloperToolbar is helpful at times like this as you can see the cookies set for your application.
Session ID resetting may have many causes. However any mentioned above doesn't relate to my problem. So I'll describe it for future reference.
In my case a new session created on each request resulted in infinite redirect loop. The redirect action takes place in OnActionExecuting event.
Also I've been clearing all http headers (also in OnActionExecuting event using Response.ClearHeaders method) in order to prevent caching sites on client side. But that method clears all headers including informations about user's session, and consequently all data in Temp storage (which I was using later in program). So even setting new session in Session_Start event didn't help.
To resolve my problem I ensured not to remove the headers when a redirection occurs.
Hope it helps someone.
I ran into this issue a different way. The controllers that had this attribute [SessionState(SessionStateBehavior.ReadOnly)] were reading from a different session even though I had set a value in the original session upon app startup. I was adding the session value via the _layout.cshtml (maybe not the best idea?)
It was clearly the ReadOnly causing the issue because when I removed the attribute, the original session (and SessionId) would stay in tact. Using Claudio's/Microsoft's solution fixed it.
I'm on .NET Core 2.1 and I'm well aware that the question isn't about Core. Yet the internet is lacking and Google brought me here so hoping to save someone a few hours.
Startup.cs
services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
builder
.WithOrigins("http://localhost:3000") // important
.AllowCredentials() // important
.AllowAnyMethod()
.AllowAnyHeader(); // obviously just for testing
}));
client.js
const resp = await fetch("https://localhost:5001/api/user", {
method: 'POST',
credentials: 'include', // important
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
Controllers/LoginController.cs
namespace WebServer.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
[HttpPost]
public IEnumerable<string> Post([FromBody]LoginForm lf)
{
string prevUsername = HttpContext.Session.GetString("username");
Console.WriteLine("Previous username: " + prevUsername);
HttpContext.Session.SetString("username", lf.username);
return new string[] { lf.username, lf.password };
}
}
}
Notice that the session writing and reading works, yet no cookies seem to be passed to the browser. At least I couldn't find a "Set-Cookie" header anywhere.

Cookies NULL On Some ASP.NET Pages (even though it IS there!)

I'm working on an ASP.NET application and I'm having difficulty in understanding why a cookie appears to be null.
On one page (results.aspx) I create a cookie, adding entries every time the user clicks a checkbox. When the user clicks a button, they're taken to another page (graph.aspx) where the contents of that cookie is read.
The problem is that the cookie doesn't seem to exist on graph.aspx. The following code returns null:
Request.Cookies["MyCookie"];
The weird thing is this is only an issue on our staging server. This app is deployed to a production server and it's fine. It also works perfectly locally.
I've put debug code on both pages:
StringBuilder sb = new StringBuilder();
foreach (string cookie in Request.Cookies.AllKeys)
{
sb.Append(cookie.ToString() + "<br />");
}
this.divDebugOutput.InnerHtml = sb.ToString();
On results.aspx (where there are no problems), I can see the cookies are:
MyCookie
__utma
__utmb
__utmz
_csoot
_csuid ASP.NET_SessionId
__utmc
On graph.aspx, you can see there is no 'MyCookie'
__utma
__utmb
__utmz
_csoot
_csuid ASP.NET_SessionId
__utmc
With that said, if I take a look with my FireCookie, I can see that the same cookie does in fact exist on BOTH pages! WTF?!?!?!?! (ok, rant over :-) )
Has anyone seen something like this before? Why would ASP.NET claim that a cookie is null on one page, and not null on another?
This was happening because I was running the app under a different virtual directory. When I ran it on the original one, it worked.
I would suggest loading the IIS debug diagnostics tools. It is entirely possible that on that particular server there is a resource problem or unhandled exception that is killing that particular cookie AFTER it is added to the response but before it is flushed to the user. This is basically caused by a series of exceptions that occur in rapid succession causing rapid fail protection to shut down the w3wp.exe process that your page is running under. When the process is spooled back up to feed the response, the cookie is gone and all that goes out is the rendered html.
You might also try turning off rapid fail protection or altering memory settings/recycling settings on the application pool.

How do I open a new window with javascript and use the parent window's existing session?

I am opening a window with window.open and I am losing the server session.
Is there a way to open a window with Javascript and use the same session?
I need this working in IE 7 and higher.
I am working with ASP.NET on the server side. The sever does not have a sessionless cookie state. <sessionState mode="InProc" timeout="15" />
It looks like you have enabled cookieless session state.
The approach for ASP.NET is similar to the one Pekka mention for PHP, but you need to call
window.open("/(S(<%= Session.SessionID %>))/NewPage.aspx");
Or change your web.config to force cookies for sessions.
I don't know what server side language you are working with, but usually, you can use a GET parameter to populate your session into the new window.
In PHP, you could use something like this:
window.open("newurl.php?PHPSESSID=<? echo session_id(); ?>");
I think PHP continues the session using the ID it got that way (never tried it actually but should work). If not, you would check for the existence of the GET variable, and force the session ID upon the script using session_id() with the ID as parameter before session_start().

Logoff button IIS6 ASP.NET Basic Authentication

I have a requirement for an explicit logout button for users in a ASP.NET web app. I am using IIS6 with Basic Authentication (SSL). I can redirect to another web page but the browser keeps the session alive. I have googled around and found a way to do it by enabling an active x control to communicate with IIS and kill the session. I am in a restricted environment that does not allow forms authentication and active x controls are not forbidden as well. Has anyone else had this requirement and how have you handled it?
Okay that is what I was afraid of. I have seen similar answers on the net and I was hoping someone would have a way of doing it. Thanks for your time though. I guess I can use javascript to prevent the back button like the history.back()
I was struggling with this myself for a few days.
Using the IE specific 'document.execCommand('ClearAuthenticationCache');' is not for everyone a good option:
1) it flushes all credentials, meaning that the user will for example also get logged out from his gmail or any other website where he's currently authenticated
2) it's IE only ;)
I tried using Session.Abandon() and then redirecting to my Default.aspx. This alone is not sufficient.
You need to explicitly tell the browser that the request which was made is not authorized. You can do this by using something like:
response.StatusCode = 401;
response.Status = "401 Unauthorized";
response.AddHeader("WWW-Authenticate", "BASIC Realm=my application name");
resp.End();
This will result in the following: the user clicks the logout button ==> he will get the basic login window. HOWEVER: if he presses escape (the login dialog disappears) and hits refresh, the browser automagically sends the credentials again, causing the user to get logged in, although he might think he's logged out.
The trick to solve this is to always spit out a unique 'realm'. Then the browser does NOT resend the credentials in the case described above. I chose to spit out the current date and time.
response.StatusCode = 401;
response.Status = "401 Unauthorized";
string realm = "my application name";
response.AddHeader("WWW-Authenticate", string.Format(#"BASIC Realm={0} ({1})", realm, DateTimeUtils.ConvertToUIDateTime(DateTime.Now)));
resp.End();
Another thing that you need to do is tell the browser not to cache the page:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetExpires(DateTime.MinValue);
Response.Cache.SetNoStore();
With all these things in place it works (for me) in IE, but until now I still wasn't able to prevent firefox from logging in the user when the user first presses escape (hides the basic login dialog) and then refresh (F5) or the browsers back button.
The Session.Abandon method destroys all the objects stored in a Session object and releases their resources. If you do not call the Abandon method explicitly, the server destroys these objects when the session times out.
Have you tried calling Session.Abandon in response to the button click?
Edit:
It would seem this is a classic back button issue.
There is very little you can do about the back button. Imagine the user has just opened the current page in a new window then clicked the logOut button, that page appears to log out but it will not immediately affect the content of the other window.
Only when they attempt to navigate somewhere in that window will it become apparent that their session is gone.
Many browsers implement the back button in a similar (although not identical) way. Going back to the previous page is not necessarily a navigation for a HTML/HTTP point of view.
This is a solution for this problem that works in IE6 and higher.
<asp:LinkButton ID="LinkButton1" runat="server" OnClientClick="logout();">LinkButton</asp:LinkButton>
<script>
function logout()
{
document.execCommand("ClearAuthenticationCache",false);
}
</script>
Found this from
http://msdn.microsoft.com/en-us/library/bb250510%28VS.85%29.aspx
Web Team in Short
Your Credentials, Please
Q: Jerry B. writes, "After the user has validated and processed his request, I now want to invalidate him. Assuming this machine is in an open environment where anyone could walk up and us it, I want to throw a new challenge each time a user accesses a particular module on the Web."
A: This is a frequently requested feature of the Internet Explorer team and the good people over there have given us a way to do it in Internet Explorer 6.0 SP1. All you need to do is call the execCommand method on the document, passing in ClearAuthenticationCache as the command parameter, like this:
document.execCommand("ClearAuthenticationCache");
This command flushes all credentials in the cache, such that if the user requests a resource that needs authentication, the prompt for authentication occurs again.
I put this on my logout link button and it works in IE6 sp1 and higher:
OnClientClick="document.execCommand('ClearAuthenticationCache');"

Resources