Stopping ASP.net concurrent logins

I’ve been working on a subscription site, logins are powered by the ASP.net membership provider system.

Now I want to stop people sharing their logins and avoiding paying for a subscription. We don’t really want multiple logins from the same username.

After a lot of Googling I came up with an almost suitable solution:

http://www.eggheadcafe.com/articles/20030418.asp

The only problem for me is that this solution stops a new login. This means that if a user logs in, closes the browser, and then logs in again, they are denied a login for the next twenty minutes (or however long the session timeout is set to).

So I switched things around, and actually ended up with a slightly simpler solution.

In my asp:Login control’s LoggedOn event I have the following:

protected void LoginMain_LoggedIn(object sender, EventArgs e)
{
    System.Web.UI.WebControls.Login senderLogin = sender as System.Web.UI.WebControls.Login;

    string key = senderLogin.UserName + senderLogin.Password;

    TimeSpan TimeOut = new TimeSpan(0, 0, HttpContext.Current.Session.Timeout, 0, 0);

    HttpContext.Current.Cache.Insert(key,
        Session.SessionID,
        null,
        DateTime.MaxValue,
        TimeOut,
        System.Web.Caching.CacheItemPriority.NotRemovable,
        null);

    Session["username"] = key;
}

We concatonate the username and password as before and use this as the key for a cache item. The cache item value though is set to the just logged in users SessionID. We then add the key to a session variable.

In global.asax we have:

protected void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
{
    if (HttpContext.Current.Session != null)
    {
        if (Session["username"] != null)
        {
            string cacheKey = Session["username"].ToString();
            if ((string)HttpContext.Current.Cache[cacheKey] != Session.SessionID)
            {
                FormsAuthentication.SignOut();
                Session.Abandon();
                Response.Redirect("/errors/DuplicateLogin.aspx");
            }

            string user = (string)HttpContext.Current.Cache[cacheKey];
        }
    }
}

This will fire for every request. If the username session variable exists then the SessionID is taken from the cache and compared to the current SessionID. If they don’t match then the user is kicked to an error page after being logged out and Session.Abandoned.

This means that a second user logging in will change the cached SessionID and login fine, whilst the original user will be logged out.

The error message explains what has happened and provides support for what to do. Which is of course either, stop cheating me out of cash, or let us know if you think your account is compromised.

15 thoughts on “Stopping ASP.net concurrent logins”

  1. I’m a bit late to the party here, but was just wondering why you included the password in the Session key?

    Wouldn’t it be sufficient just to use the username, and be a little more secure not to use the password in this way?

    Steve

  2. You know what Steve, I can’t rightly remember and I can’t think of a good reason why when thinking of it afresh. Good point.

  3. Hi, I encounter a problem that if 2 different user id login, the 1st login user will be logged out even both user ids are different. Is there any way to prevent this happen? thx

  4. I’m a bit late to the party here too :), but was just wondering what if a specific user opened the application in more than one window (IE tabs for example) ??!! he will be kicked to the error page ??!!

  5. Hi All, What is user closes the browser and tries to log in again. Will the previous session get closed. My session timeout is 60 min.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>