Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When the same user ID is trying to log in on multiple devices, how do I kill the session on the other device?

What I want to do is to limit a user ID to only being able to log in to one device at a time. For example, user ID "abc" logs in to their computer. User ID "abc" now tries to log in from their phone. What I want to happen is to kill the session on their computer.

The Spotify app does exactly this- Spotify only allows one User ID to be logged in on one device at a time.

I'm using ASP.NET membership (SqlMembershipProvider) and Forms Authentication.

I've experimented with Session variables but I'm not sure exactly where to go from here.

like image 364
Mike Marks Avatar asked Apr 09 '13 13:04

Mike Marks


People also ask

How do I prevent different users from logging into other devices?

First could be to include the user's IP address in your data (database, cache, token, etc). Then you could verify that the IP address of the first login is being used, and block all other login attempts or subsequent requests from any other IPs for the given user.

How can I stop multiple logins from same user in MVC?

The solution is somewhat more simple than you have started implementing. But the idea is the same: every time user logs in, change their security stamp. And this will invalidate all other login sessions. Thus will teach users not to share their password.

How do I prevent multiple log-ins on the same device?

There are a number of apps out there that prevent multiple log-ins- for example, Spotify. Spotify will only allow one log-in at a time, no matter the device. Spotify logs the user ID out of another device (phone, computer, etc.) if the same user ID has logged in to a new device. Out of the box, ASP.NET allows for concurrent log-ins.

What happens when the same user logs into the application twice?

When same user logs into the application from different browsers or devices we validate one login session and invalidate the other and allow the valid session to perform actions in the application. We deny any action the user performs from the invalid session and logout that session. The session id is stored in the table.

How does Spotify log users on multiple devices?

Spotify logs the user ID out of another device (phone, computer, etc.) if the same user ID has logged in to a new device. Out of the box, ASP.NET allows for concurrent log-ins.

What is the difference between userid and sessionid and loggedin?

UserId is pretty self-explanatory, SessionId is the current Session ID (explained below how to get), and LoggedIn is simply a Boolean that's initially set to True upon a successful user log-in. I place this "insert" logic inside my Login method of my AccountController upon successful validation of the user- see below:


1 Answers

I came up with a pretty awesome solution to this. What I've implemented was when user "Bob" logs in from their PC, and then the same user "Bob" logs in from another location, the log-in from the first location (their PC) will be killed while allowing the second log-in to live. Once a user logs in, it inserts a record into a custom table I created called "Logins". Upon a successful log-in, one record will be inserted into this table with values for "UserId, SessionId, and LoggedIn". UserId is pretty self-explanatory, SessionId is the current Session ID (explained below how to get), and LoggedIn is simply a Boolean that's initially set to True upon a successful user log-in. I place this "insert" logic inside my Login method of my AccountController upon successful validation of the user- see below:

Logins login = new Logins(); login.UserId = model.UserName; login.SessionId = System.Web.HttpContext.Current.Session.SessionID;; login.LoggedIn = true;  LoginsRepository repo = new LoginsRepository(); repo.InsertOrUpdate(login); repo.Save(); 

For my situation, I want to place the check on each of my controllers to see if the currently logged in user is logged in elsewhere, and if so, kill the other session(s). Then, when the killed session tries to navigate anywhere I placed these checks on, it'll log them out and redirect them to the Log-in screen.

I have three main methods that does these checks:

IsYourLoginStillTrue(UserId, SessionId); IsUserLoggedOnElsewhere(UserId, SessionId); LogEveryoneElseOut(UserId, SessionId); 

Save Session ID to Session["..."]

Before all of this though, I save the SessionID to the Session collection inside the AccountController, inside the Login ([HttpPost]) method:

if (Membership.ValidateUser(model.UserName, model.Password)) {      Session["sessionid"] = System.Web.HttpContext.Current.Session.SessionID; ... 

Controller Code

I then place logic inside my controllers to control the flow of the execution of these three methods. Notice below that if for some reason Session["sessionid"] is null, it'll just simply assign it a value of "empty". This is just in case for some reason it comes back as null:

public ActionResult Index() {     if (Session["sessionid"] == null)         Session["sessionid"] = "empty";      // check to see if your ID in the Logins table has LoggedIn = true - if so, continue, otherwise, redirect to Login page.     if (OperationContext.IsYourLoginStillTrue(System.Web.HttpContext.Current.User.Identity.Name, Session["sessionid"].ToString()))     {         // check to see if your user ID is being used elsewhere under a different session ID         if (!OperationContext.IsUserLoggedOnElsewhere(System.Web.HttpContext.Current.User.Identity.Name, Session["sessionid"].ToString()))         {             return View();         }         else         {             // if it is being used elsewhere, update all their Logins records to LoggedIn = false, except for your session ID             OperationContext.LogEveryoneElseOut(System.Web.HttpContext.Current.User.Identity.Name, Session["sessionid"].ToString());             return View();         }     }     else     {         FormsAuthentication.SignOut();         return RedirectToAction("Login", "Account");     } } 

The Three Methods

These are the methods I use to check to see if YOU are still logged in (i.e. make sure you weren't kicked off by another log-in attempt), and if so, check to see if your User ID is logged in somewhere else, and if so, kick them off by simply setting their LoggedIn status to false in the Logins table.

public static bool IsYourLoginStillTrue(string userId, string sid) {     CapWorxQuikCapContext context = new CapWorxQuikCapContext();      IEnumerable<Logins> logins = (from i in context.Logins                                   where i.LoggedIn == true && i.UserId == userId && i.SessionId == sid                                   select i).AsEnumerable();     return logins.Any(); }  public static bool IsUserLoggedOnElsewhere(string userId, string sid) {     CapWorxQuikCapContext context = new CapWorxQuikCapContext();      IEnumerable<Logins> logins = (from i in context.Logins                                   where i.LoggedIn == true && i.UserId == userId && i.SessionId != sid                                   select i).AsEnumerable();     return logins.Any(); }  public static void LogEveryoneElseOut(string userId, string sid) {     CapWorxQuikCapContext context = new CapWorxQuikCapContext();      IEnumerable<Logins> logins = (from i in context.Logins                                    where i.LoggedIn == true && i.UserId == userId && i.SessionId != sid // need to filter by user ID                                   select i).AsEnumerable();      foreach (Logins item in logins)     {         item.LoggedIn = false;     }      context.SaveChanges(); } 

EDIT I just also want to add that this code ignores the capability of the "Remember Me" feature. My requirement didn't involve this feature (in fact, my customer didn't want to use it, for security reasons) so I just left it out. With some additional coding though, I'm pretty certain that this could be taken into consideration.

like image 68
Mike Marks Avatar answered Oct 16 '22 21:10

Mike Marks