views:

2472

answers:

6

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()

A: 

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.

AnthonyWJones
when I click back I am still authenticated.protected void logOut_Click(object sender, EventArgs e) { Session.Clear(); Session.Abandon(); ViewState.Clear(); FormsAuthentication.SignOut(); Response.Redirect("http://www.google.org"); }
willyconnor
+1  A: 

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.

Ken Browning
when I click back I am still authenticated.protected void logOut_Click(object sender, EventArgs e) { Session.Clear(); Session.Abandon(); ViewState.Clear(); FormsAuthentication.SignOut(); Response.Redirect("http://www.google.org"); }
willyconnor
This sounds like you're viewing a cached version of the page. If you try and force a refresh from the server, you will notice a that the session has expired.
Ken Browning
I should also note that you can disable caching. There are several stackoverflow questions which explain how this is accomplished.
Ken Browning
@Ken: content made available via the back button does not necessarily come from the cache or honor the servers supplied cache control headers. The back button facillity is beyond the remit of the HTTP protocol is entirely at the browsers discretion.
AnthonyWJones
Good point, thank you.
Ken Browning
okay I have set a custom http header control for the cache like this Cache-Control:no_cache I have also clicked the logout button then deleted the cache. But the back button still brings me back to an authenticated session. Thanks Ken and Anthony. Your comments have given me avenues to investigate.
willyconnor
the http header was set in IIS and I verified it by using the Live HTTP headers extention for firefox. I also verified the the cache is being destroyed with Cache Viewer another Firefox add on. Is it possible that the browser is keeping a session alive? Do you know of any way to test for this?
willyconnor
AnthonyWJones pointed out that your browser may show your page when the user presses the back button even if the page is set not to cache. This is the prerogative of the browser and (depending on the browser) likely out of your control. This doesn't mean a session is still active.
Ken Browning
You should be able to figure out a way to test this yourself. Create a test page which shows a session variable. Logout. Navigate to that page and make sure its refreshing from the server (and NOT coming from the browser cache). You will not see the session variable's value.
Ken Browning
A: 

hi,

i am using window.history.forward()..in javascript for redirecting the user to forward from the current page..but is not working in mozilla as well as IE.. could youplease suggest what i have to use?

ex : - window.history.forward()

Thanks Ram

A: 

@Ram : window.history.back(-1);

A: 

This is a solution for this problem that works in IE6 and higher.

LinkButton

function logout() { document.execCommand("ClearAuthenticationCache",false); }

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');"

willyconnor
+2  A: 

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.

TweeZz