Hi, my name is Mykola Pidopryhora and I’m a Web and .Net software engineer at EGO. Recently I worked on the project in which I faced a specific task – securing ASP.NET MVC application. To solve this task I searched for answers in the Internet, but as it turned out there was no complete solution for this problem. So, I decided to invent my own.
Today I would like to share this ready-to-use solution with you, so you can save some time for a cup of tea with a cookie. Just take it and use
Let’s get down
Sometimes we need to implement specific security rules, like user auto-logout, whenever a session is time-out or user closed his browser. There are several approaches to implementation of such behavior and very few information about how it can be done.
I’d like to introduce you one of the approaches that allows you to use your set of actions on user’s browser close event. It may seem tricky and so it is. Anyway, to keep it simple I tried to make it in a guide style. Here is an example of how to implement a user auto log out in ASP MVC.
It includes handling the following scenarios:
- log out user when a session is expired
- log out user and run custom commands after a tab/browser was closed
- log out user after navigation to a login page
- handling work with a load balancer
The example was built from ASP.NET 4.6.1 MVC with Individual User Accounts
Here the key points of the idea are described, you can find the source code on GitHub.
Use session timeout to kick out user
- Setting session timeout in web.config
In order a user to be logged out after a session expiration he should make a request.
- Let’s add a bundle and some scripts for that
Following script will do one simple thing: starts a timer with timeout equals to session timeout. When the time is out it will submit a logout form with a session expired flag.
- Let’s add a helper function that will allow us to pass the value from server to client script.
Use separate layout for authorized and unauthorized site resources:
And use added function and bundles for authorized layout:
This way we get a user kicked out when session is expired. The server side will be also notified whether user pressed logout manually or has been kicked out automatically.
Implementation of user kick out on browser/tab close for non-load balancer system
The following approach may be used for systems without a load balancer, which are using one place for sessions.
In order to implement such application behavior, I will use WebBackgrounder library, which you can find here.
Approach general overview: keep every user’s session in a collection and clear the sessions during which user`s browser didn’t send a ping request in time (when browser was closed).
- Let’s start from adding a job that will keep and handle sessions:
- In order to keep a single sessionId per request let’s add Session_Start callback as well:
- Let’s add Ping action and OnAuthorization filter into BaseController:
- Also we need to clear session on user logout manually and inherit controllers from BaseController:
- And finally let’s add a script that will send a ping request to address, which we have passed into it:
- Let’s make some modification in actions:
- Now we need to add some request filtering and disable browser cache:
Well, that’s should be enough.
You can play with timings of ResetPingStatusJob, session timeout and pingActionInterval to get a user logged out after the time period you want. With current timings user will be logged out approximately after 30 seconds since browser / tab has been closed.
But I’d like to add one more thing…
Let`s make a user logged out on navigating to login page
- And update login layout with using bundles:
Using application with load balancer
If you are going to use load-balancer, you need to implement custom session storage provider or use default session storage with sql job that will clear session with task like this:
In this case you don’t need the implementation of PingJob, which described above, but you’ll still need a ping action and session-ping.js.
Here is an example of such MS SQL job :
I hope this will help you. Good luck!