I'm working on an ASP.NET application where our users authenticate using client certificates over HTTPS. Our users are only using IE7.
Once a client certificate has been used to authenticate successfully it stays in the browser's SSL cache until the process is closed or the user manually clears the SSL cache. We want to be able to clear the SSL cache whenever a user logs out, or their session expires, to improve the security of the system.
Our clients already use smartcards to access the system, which unload certificates automatically when the card is removed from the client computer, but this does not clear the browser cache at all, leaving a potential avenue of attack from another user who had access to the same machine as the genuine user.
I've found out how to do the actual cache clearing from JavaScript:
document.execCommand("ClearAuthenticationCache");
which works perfectly when a user explicitly logs out, as we can execute the script on the client before allowing the user to log in again.
NOTE: IE7 only lets the cache be cleared programmatically when HTTP Keep-Alives are disabled on the web server.
Here's the tricky bit - if a client's session expires, I don't know of any way to handle this in the browser before the user tries to login again. I can't clear the state when they get to the login page, because I need the state cleared and a new certificate chosen before the page executes on the server.
Any ideas? Apologies for length of question, but background is important for this one.
Never mind, I came up with a good solution:
When the user successfully logs in, we create an additional session cookie that doesn't expire until the browser is closed.
If the user comes back to the login page later and the request is unauthenticated, we check for the existence of the session cookie - if it exists, we know that the user has previously had a session, so we explicitly log them out, exactly as we do for the user-initiated logout. If the session cookie doesn't exist then we attempt to automatically log the user in using their certificate.
The custom session cookie is deleted for each explicit log out, and re-populated for each successful login.
This gives us the best experience for the user, and guarantees that a certificate will be cached only as long as a session is still valid (15 minutes, sliding). Also, the session cookie cannot be removed by the user so there is no way to bypass this behaviour. They can't use the site without accepting session cookies either.
Related
My requirement is user should not log in from multiple browser or system simultaneously in application. For this I maintained the flag in database, so whenever user is logged in I am updating flag as yes and when he logged out I am updating it as no.
My issue is if user close the browser window without logging out from application then I am unable to update the flag. So next time when user try to logging in application, It is saying user is already logged in.
I tried using Onbeforeunload event in master page, but whenever I am changing the menu in my application. It is firing that event. For updating the flag I used page methods. But this is not working properly.
I would say, send often via a ajax call to your API that a 'ping' to confirm you are still online. If there is no ping or page change after 3 minutes, I consider the user has been logged off and it sets him as "logged off" in database.
At least, I do this using javascript, but i'm sure you can also in your client-side part of the ASP.NET app you are making.
You can't handle this only by client-side code, using e.g. beforeunload, because the page/browser may be closed for many reasons (e.g. lack of electricity).
What you can do is:
Scheduler on your backend which verifies whether an user did some action since e.g. 1min. In that case you have to update information about user action in your DB after every ajax requests (Hugo Regibo suggested ping requests).
Disadvantage od this solution is this period - when an user turns off the page then he will be not able to log in again for 1min.
Instead of a scheduler you can verify logged-in users (I assume you keep them in a DB table) after each requests.
Use web sockets, you will have continuous connection and you will be notified about closed connection immediately. Disadvantage of this is web sockets don't scale so good as stateless HTTP.
Besides that I don't know whether you use iis with a session provider or not? And when an user closes the page and opens it again should be able to log in with his saved credentials. You should write more of how your project looks like.
I would do it by saving a Session object for each login call. A session ID would then be stored in the user's cookie or authentication token. Each call to the system would validate the user via their session ID. If that session has been invalidated, they just get sent to the login prompt. Whenever the user logs in, it invalidates all of their other sessions.
This way the user could be in their browser on their machine, navigate away, close the browser, and come back to find their session still alive without having to log back in. But, if they log into another machine, then their old session would be invalidated.
I am using an MVC app to manage authentication. The issue I have is with chrome because it never actually kills the session because it runs in the background after it closes by default. I do not want to enforce all the end users to change this setting because then it will kill hangouts etc.. So I am wondering if I can use any standard web.config setting to handle this or do I need to make an ajax polling interval to keep updating the cookie expiration?
The ASP.NET session consists of 2 components the client-side http session cookie and the server's session storage provider. Suppose user has SessionId 1. If you delete session 1 from the server, the user returns and a new session is created with SessionId 1. If the user deletes the session cookie, the server keeps running session 1.
What you're asking for is generally not possible. There's no way you can force a user to send a request to your server when they are exiting your site or the browser. There is the javascript beforeUnload event which in some situations would allow you to send a request to /sign-off in some situations. The obvious limiter is no network access = no message.
The standard resolution for orphaned sessions is for session scavenging policy to clean them up. Some developers choose to use persistent storage to eliminate scavenging altogether such that a shopping cart would never disappear.
The only reasonable solution (which is still overkill) that would reach your goals. You use SingalR for a persistent connection of the user to the server and you ping them from the server. If the connection fails to respond you abandon the session. This will be a fragile process and if you don't make very very sure the user is disconnected you will have lots of support calls from users wondering why they are continuously logged out while browsing your site on cell phone.
If the session is stored in proc
The user logs in, closes the browser directly and reopens it after an hour. Would he need to log in again?
If the web application uses cookies and cookies are enabled on the users browser...
If the web application uses persistent cookies and cookies are enabled on the users browser...
If the web application uses cookies and cookies are disabled on the users browser...
If the web application uses persistent cookies and cookies are disabled on the users browser...
If session is stored in state server and situations are the same, then what would happen?
When a session is created (assuming it is a normal session), a cookie is sent to the browser that looks something like this:
SESSION_ID=437b930db84b8079c2dd804a71936b5f
Sessions can be used without cookies if the session identifier (in the example above, 437b930db84b8079c2dd804a71936b5f) is passed around as request parameter instead of a cookie; however, this is rather uncommon and it is generally considered bad practice.
All session information is stored server-side, and the session identifier is used behind-the-scenes to decide which set of information should be recalled (if any) for each request. Thus we get to your questions.
If the web application uses cookies and cookies are enabled on the users browser...
If the web app uses cookies and cookies are enabled on the browser, then there should not be a problem. With a standard session implementation, the cookies will be non-persistent, though, so the user will need to login again if he/she completely closes all instances of the browser.
If the web application uses persistent cookies and cookies are enabled on the users browser...
If the session-id is stored in a persistent cookie and user's browser respects that by persisting the session identifier cookie to the disk, then the session identifier will be sent even if the browser is fully closed and restarted. However, please be aware that most web frameworks have a garbage-collector-like system that deletes data for sessions that have showed any activity over a certain amount of time. So, for example, let's say my website requires activity at least once every 4 hours to keep a session active. If I login, receive a persistent cookie with my session ID, close my browser, and come back 5 hours later, then I will need to login again because my session information would have been cleared from the server even though my session ID cookie was persistent.
If the web application uses cookies and cookies are disabled on the users browser...
Bad news bears. You will either need to find a way to use a cookieless session (passing an identifier as a parameter for each request), or you will need to ask the user to enable cookies. There is no way around this.
If the web application uses persistent cookies and cookies are disabled on the users browser...
Same situation as #3. If the user has cookies disabled, you are out of luck. Either they need to enable cookies (at least for your site), or you need to find another way to pass around information between requests.
Session is stored in server memory (unless a state server or persistant store is used) but relies on a cookie to identify the session. If cookies aren't available then session won't work since there is no way to identify the user. Cookieless sessions can be used to get around this. Cookieless sessions aren't recommended as they can be hijacked with the session identifier in the url.
If an expiration isn't set on the cookie then it will be lost once the user closes all browser instances (they share memory) and not just the one visited through the website.
If the user has cookies disabled, then cookies aren't available for use by the application. People aren't as worried about cookies now as they were in the late 90's (lots of "security" people raised warnings that cookies could be used to store all sorts of things on your computer, even viruses).
Is there a way to remove the authentication cookie, or sign a user out once they are removed from the asp.net membership database? By default if a user is removed from the database, the user can still browse the website since they still have a valid authentication cookie.
I've tried different things within global.asax but nothing seems to work. Is something like this even possible?
See here: FormsAuthentication.SignOut Method. Although this refers to users not being logged out server side, a similar approach can be used for managing deleted users.
Calling the SignOut method only removes the forms authentication cookie. The Web server does not store valid and expired authentication tickets for later comparison. This makes your site vulnerable to a replay attack if a malicious user obtains a valid forms authentication cookie. To improve security when using a forms authentication cookie, you should do the following:
Use absolute expiration for forms authentication cookies by setting the SlidingExpiration property to false. This limits the window in which a hijacked cookie can be replayed.
Only issue and accept authentication cookies over Secure Sockets Layer (SSL), by setting the RequireSSL property to true and by running the entire Web site under SSL. Setting the RequireSSL property to true ensures that ASP.NET will never send an authentication cookie to the browser over a non-SSL connection; however, the client might not honor the secure setting on the cookie. This means the client might send the forms authentication cookie over a non-SSL connection, thus leaving it vulnerable to hijack. You can prevent a client from sending the forms authentication cookie in the clear by running the entire Web site under SSL.
Use persistent storage on the server to record when a user logs out of the Web site, and then use an application event such as PostAuthenticateRequest event to determine whether the current user was authenticated with forms authentication. If the user was authenticated with forms authentication, and if the information in persistent storage indicates the user is logged out, immediately clear the authentication cookie and redirect the browser back to the login page. After a successful login, update storage to reflect that the user is logged in. When you use this method, your application must track the logged-in status of the user, and must force idle users to log out.
The third option is the most secure but requires the most effort. IMO, the first two do not resolve the issue adequately.
It is also possible to store custom information in the Forms Authentication Ticket. You could store the last explicit logout time in this ticket, and check it against your server side database record. Please note that if this record is at user level instead of session, then all logins under that account would be logged out at the same time.
In your case, if you are deleting server side user and session records, as the record does not exist you will be able to also fail the authentication request.
I'd advise also storing and checking the last date/time the password was changed - that way if a user updates their password then all existing sessions are logged out.
Suppose I have logged into an application which is running from IIS. Now I haven't logged out, but closed the browser. And when I'm accessing the application again, it defaults to the login page. How does IIS recognize that it is a new request and redirects the user to the login page?
I have another question. Suppose if I'm not closing the browser, which I used when I logged in. I'm opening the new browser to request a page from same application. IIS recognizes that it's a new request to the application and redirects the user to login page. Why does it not use the existing session or cookies which the first browser uses?
Please don't get irritated of my continuous questions... I am having huge confusion.
We say HTTP is a stateless protocol. Once the page is requested I have logged in. And the HTTP protocol connection will be terminated between IIS and browser, right? Then I am navigating to other pages in that logged in application. Now IIS recognises the user has logged in on this browser. But when I open a new browser and request that application, how does IIS recognises it is a new request? Since the HTTP protocol is disconnected, how does it work in the first case?
As you've correctly said, HTTP itself is stateless, and each request is technically separate from every other. Sessions, as used by web sites, are a workaround for that. What happens, normally, is that the server stores whatever info it cares to maintain between requests (like the logged-in user's username and/or ID, for example), and assigns that information an ID (called a "session ID"). It then tells the browser that session ID, in such a way that the browser can hand the ID back when it's time to make another request. If the browser plays its part and provides the session ID, then the stored information can be retrieved, updated, etc with each request, providing some degree of state even over a stateless protocol.
Sessions are usually implemented using cookies. That is, the server hands the browser a cookie with the session ID, and the browser hands back that same cookie with each request until the cookie expires or is otherwise forgotten. Some cookies (so-called "session cookies") aren't saved, and are forgotten when the browser is closed. A freshly opened browser doesn't have any session cookies to pass, so if the server uses session cookies to do sessions (which it should), it will consider the user not yet logged in and bounce them to the login page if they need to be logged in.
Session cookies will usually be shared between tabs in the same browser, and will sometimes even be shared by windows opened by "File > New Window" from an already running browser, because both of those cases will typically just be a part of that browser. But if you start the browser from the Start menu, or however your OS lets you start a program, it's a whole other process -- and session cookies are rarely shared between processes.
The server typically also only remembers sessions on its end for a limited time (anywhere from seconds to years, depending on the server and/or site settings) after each request that uses the session. If the browser passes a cookie that corresponds to a session the server no longer remembers, it'll act as if there's no session at all. Which, in cases where you have to log in, will again bounce to the login page.
There are cookies that are passed always no matter are you logged or not. They are mapped to session in IIS.
Check out the following articles. They might be helpful.
IIS Dropping Sessions
Session Management in ASP.NET