How to Make User Login from Only One Device At a Time

Only allow signing in from one device at a time in NodeJS

That's pretty much your only option, the JWT is pretty stateless on purpose. Similar to how you can't really do a server side logout without similar technique

As jfriend points out, storing the JWT alone is insufficient. What you need to do with it is ensure that the next time a user requests login, that they don't already have an unexpired JWT issued to them.

Going through the flow for completeness:

Case 1: User isn't logged in anywhere. In this case, JWT is issued and stored. Possibly in the user record for easy retrieval.

Case 2: User tries to log in on another device. Whether you make them explicitly log out of the first device or do it for them, you have to now send that stored token into a list of revoked tokens. Your token validation logic will have to take that list into account when determining if a token is valid or not.

/* Further clarification */

I feel like a bit more detail might be useful for folks, so I'm going to go into implementation a bit.

** Unauthenticated requests **

This shouldn't change, but it's worth mentioning that I'm assuming you have routes that require authentication, and requests to those routes which do not include an active and valid JWT get rejected with a 401 (and probably provided the URL to the login url).

Login

Login logic always includes a user lookup, so as described above, the flow in this application should include that lookup, but before logging the user in the application you will check to see if there's already an assigned token to the user which has not expired.

If there is not a token already assigned to the user, then check credentials however you normally would, generate a JWT (with an exp heading to indicate expiration time in the payload), save that token back in the user document/record for future reference.

If there is an assigned token which is also unexpired, then you either have to log the user out of the other device (more on that in a second), and log them in to the current device, or else you have to reject the login attempt and keep the person logged out of the new device. I think the former approach is more user friendly, but it depends on the needs of your application.

Logout

With JWT, the only way to guarantee a user is unable to use an issued token is to either include an expiration time (exp) in the payload, and use a verifier that checks that, or to know on the server which tokens are no longer valid and check against them. The most robust solutions do both.

So, assuming you're handling the expiration already the explicit logout feature would be handled by creating a revoked tokens list somewhere. If you're using MongoDB, for example, you'd create a collection to store those. You'd ideally also set a TTL on each one that is set to some point after the expiration date, so that Mongo will evict tokens that are otherwise expired anyway, to save yourself time and space.

If you're doing the auto-logout on a new login request, you'll hit this logic to place the old token into the revoked tokens list when you save the new token in the user's document.

The logout route should also be reachable by authenticated users, to explicitly logout if they want, regardless of whether you do the auto logout or not.

Authenticated Requests

By this point you should be reasonably certain that users can only login on one device. However, you also need to make sure that they aren't trying to make a request with a revoked token.

Your generalized route security middleware would then need to also check the revoked token list to see if the token offered by the client is on said list after checking to make sure it's not expired (since the expiry can be checked upon validation, saving a round-trip to the DB.

Enable login to one device at a time

I don't think accepted answer is a correct solution. You should not have this logic on client side. This could lead to potential security issues.

All you need to do is invalidate the old oauth token on the server side, so the next time the old device uses the old token it would receive, 400 invalid_grant exception, that's when you have to perform a log out.

Logic for (one user can login from one gmail and from the same device only) using google auth in flutter?

Is there any idea to restrict the user so that they are active from only one device always?

Sure you can. The simplest solution would be to store the device ID in Firestore. Once the user tries to authenticate, check the value from Firestore against the actual device ID. If you get a match, continue with the authentication process, otherwise, display a message, or do whatever you need.



Related Topics



Leave a reply



Submit