Node.js one session per user - node.js

How can I prevent my users to be logged in my system from two devices same time? So if user logged in from computer, when he logins from different computer, session on first automatically closes (don't need make it realtime).
I use node.js, express.js, mongoose, passport, connect-mongo (to store sessions in database).

You can generate a token when user logs in and save it in your database against that user. Now with each request you will need to send this token to server. Consider the following scenario:
User A logs in from Computer A and a token 123 is generated and saved in database. Now whenever User A sends a request to server, it first checks for a valid session and then loads user's token from database to check if its valid.
Now User A logs into the website from Computer B and a token 456 is assigned to the user and is overwritten in database. Next time when User A sends a request from Computer A, server checks for a valid session and when it gets the token from database there is a mismatch indicating that user has logged in from somewhere else so current session is invalid.

Related

jwt token how to ensure the payload is updated when database change

I have a question regarding the concept of JWT token type of authentication.
So suppose I sign a jwt token after user logged in, the token payload contains the username and userRole. I then return the token to the user and store in user's localStorage.
Now, if i change the userrole in database, i.e. from normalUser to AdminUser, how can I then ensure the payload on user's localStorage also change?
I have an issue when if the user is an admin user, when he signs in, a jwt is stored in his localStorage. Afterwards, I set his role to normal user, he can still access the admin features because his localStorage contains the role of AminUser.
Can someone suggests a correct way to implement authorization so that the token is updated on user end?
Thanks.
What is your trigger for changing the user's authorization? If you're saying that you're opening your database client (Say for example MySQL or PostgreSQL) and manually changing the authorization for the user, then there's no way your server or your client to know of that change (As far as I know at least) and they cannot react to that particular change.
If your trigger was some request sent by the user, say logout or change authorization, then you should respond with the new token for that particular request and store it, easy peasy.
If your trigger wasn't related to your client, and it's somehow something happening on your serverside, then you should have a socket opened between your server and your client, and emit that change from your server to your client.
That way you ensure the client is always up-to-date.
But that's still not enough, because yeah you're keeping the client up to date, but what if he saved the token and replaced it after your update? He/She can still access admin features even though you told them they're just normal users. For that you're gonna need to validate every request done by any of your users, and check if they're allowed to make that request in the first place.
You cannot really trust clients. You should find a way to invalidate your jwt tokens. Your client should get a new token when you reject them. You can rotate your tokens using refresh key.
In order to do that:
Keep your token lifetimes short
Or:
Store blacklisted tokens in the database and reject the invalidated tokens.

How should I handle RESTful authentication while using JWT tokens?

I have read many articles and viewed many videos but there are a lot of contradictions. I try to avoid any external libraries and build the system from scratch, I have read about oAuth 2 but it is more confusing.
This is the flow that I think is ok untill now:
User fills a form using email and password and submits it.
Server verifies the password if it matches and responds back with a httponly cookie with a signed jwt token that expires in like 10
minutes. (I know I have to protect it against csrf attacks)
User gets logged in and every new request he is making to the server he will send the cookie in the header automatically and the
server will verify the token.
Everything is fine but I have encountered some issues and have some questions:
I want the user to stay logged in even after opening a new session so there is no need to login after the token expired or when he closes the browser.
What should happen if the access token expired?
There should be a refresh token attached to the user in database that gets added when the user logs in with an expiration of ex 7 days, then the server will respond with a cookie containing that refresh token?
On the new request while access token is expired,the user will send the refresh cookie to the server, if it matches the user database refresh token,server will respond with a separate cookie that will renew the access token?
If there is a refresh token where should you store it and what format? (cookie,database or where?)
Should I keep the user logged in based on this refresh token cookie?If is it httponly I can't read it and set the state that user is logged in. How should I do it?
I heard about that revoking the jwt token is problematic. How would you fix it?
How would you do this whole thing?Please explain the workflow, I try to avoid localstorage,as I read everywhere that is not safe for sensitive data.
I have implemented and deployed to production systems that do exactly the kinds of things that you are asking about here so I think that I am qualified to provide you with some guidance to solve your particular issues and answer your questions. The flow that you have listed above in the numbered list is definitely the correct path so far. I do understand your confusion going forward from there because there are many different options for how to approach this problem.
In addition to providing a login route that returns a new JWT to the client when the user submits a login form to the server, I would recommend also implementing a token refresh route that accepts a still valid JWT that was received from the initial login process and returns a new JWT with an updated expiration time. The logic for this new token refresh route should first verify that the provided JWT is still valid by matching it with a user in the database. Then, it should generate a new token using the same JWT generation logic as the login route logic. Then, the application should overwrite the access token data in the database for the user replacing the old access token with the newly generated access token. It is not necessary to keep an old access token in the database once it is no longer valid, which is why I suggest simply overwriting it with a new one. Once all of that is finished and successful, you can return the new JWT to the client and then the client should now use that new JWT when making any additional authenticated calls to the server to maintain an authenticated interaction with the server. This logic flow would keep the user logged in, because the client would have a valid JWT before calling the refresh logic and it would have a valid JWT after calling the refresh logic. The user should only be recognized as not logged in and not authenticated if they are no longer able to provide a valid access token that is associated with a user in the database.
As far as cookies go, whichever method that you use for maintaining the cookies on your client should be used for setting the refreshed access token as it is for setting the initial access token that you receive on login. If the server finds that an access token is no longer valid at some point in the future, if for example your client is not used after login until some time after the access token has expired, then the client should recognize a server response indicating that this is the case and present the user with the login flow on the client again so that a new access token can be acquired and stored in a cookie on the client.
I would not worry about revoking JWTs and instead just let them expire if they do and initiate a new login flow if it is found that a JWT has expired. Also, instead of using local storage I would suggest using session storage to store your JWT so that you have it for the duration of your user's session on the website and it is removed as soon as the browser has been closed. This will prevent the JWT from persisting beyond the session and should assuage your fears about saving sensitive data in the session storage. Also, when generating your JWT, you should also make a point of not storing any sensitive data in it because JWTs are easily reverse-engineered. This can also prevent any sort of sensitive data from being exposed on the client.
EDIT:
The key thing to remember when developing your server API is that you should have two different classes of endpoints. One set should be unauthenticated and one set should be authenticated.
The authenticated set of endpoints would not require an access token to be included in the request. An example of this class of endpoint would be your login endpoint, which does not require an access token because it actually generates an access token for you to use later on. Any other endpoint that does not expose sensitive or important information could be included in this class of endpoints.
The unauthenticated set of endpoints would require an access token to be included in the request, and if no access token or an invalid access token is detected the endpoint would respond with a 401 HTTP response code (indicating an unauthorized request). An example of this class of endpoint would be an endpoint that allows a user to update their personal information. Obviously, a user cannot update their own information if they cannot provide credentials to prove that they are the user whose information they are attempting to update. If the client receives a response with a 401 response code, that would be the signal that the client would need in order to tell the user to re-login so that a new valid access token can be retrieved. This possibility can be avoided on the client if the client is programmed to periodically check the expiration of the JWT that is currently being held on the client and initiate an access token refresh, but obviously you should still have logic in place to detect and respond to a 401 response code so that the client user flow is managed properly.

Token Based Authenication with Node/Express

I’m a little confused as to how JWT authentication works. Once a user is able to log in, my express server is responding with a token, which I store on the client side in local storage. With every request, I send that token. My question is, how do I limit a user to see his/her specific data (e.g., user profile)? Is the token alone able to determine which user is requesting the user data on the server side or would i have to send the username along with the token? Is this secure?
The JWT token will contains 3 parts, one of them called a payload and you will use it to store the user's id when he logs in. When the user sends a request with his token you will decode it and grab the id from the payload and then with a query to your database you can get the user's profile.
how do I limit a user to see his/her specific data (e.g., user
profile)?
If you get the id from the token's payload then you can compare it with the id of the profile that the user wants to see, if they are the same then it means that he wants to see his profile.
Is the token alone able to determine which user is requesting the user
data on the server side or would I have to send the username along
with the token?
No need for username, the token alone is sufficient because it identifies the user.
Is this secure?
Read this: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/ there are other opinions of course, try implementing best practices and I think you'll be fine.

Firebase create entry when user signs in

I am trying to setup a login process for firebase. I am going to be using client side user creation (because apparently firebase only allows client side user creation), and here's what my workflow looks like:
User signs up through email and password
Service creates an entry at /users/$uid, as well as a couple others (ie /table1/$uid, /table2/$uid)
User can write to database at path /users/$uid, /table1/$uid, etc where $uid = the current logged in user (this is done via rules)
However, for number 2, I want to create the entry /users/$uid, but I dont want the user to have access to that at all. Is there any way to do this? One option I thought of was having a service account running with all r/w permissions on a node server to create those tables, but how would I call that server method if I'm doing all of the auth client side?
After step #1,
Your client code can get a Firebase token for the current login user via firebase.user.getToken()
Your client app sends the token to your node server
The node server validates the token using Firebase server SDK
The server extracts user id from token.uid.
Now you can continue step #2 to create table for the user.

NodeJs Authentication????

I'm building a apllication with NodeJs. My app have 1 login form.
When user A login successfully, I save username in session of Express.
And now I want when another user is B, login with that username, the user A 'll be logout, he 'll have a messager alert 'This account was login in another place' and user B is login.
Anyone can help me please. Thanks
Save the the user in for example a database, create a token for the specific login session and add this to the user in de database. Switch this token each login.
With each request check the authentication token (you can store tokens in local storage), then you can check if the token is up to date (active) or not.
Once another user logs in the token will change, and so on.
If you want the logout to happen without making a request you will need to use socket.io

Resources