actix-session invalidate session - rust

I'm currently using actix session with redis
for handling user sessions in web app. I cant figure out how to handle user password reset (aka. "forgot password").
What I mean by password reset:
User request password reset and receives an email with reset token
User opens form where he submits new password (with received token) to server
Server validates reset token and password and stores new hash to database
What I want to do but I have no idea how:
In step 3. I want to invalidate any previous sessions that user had.
Should I just manually find data in redis and erase it?

Related

reset password putting password into jwt payload

My one time reset password link is like this with a token http://url.com/token. The payload of the token contains a password (hashed)
When the user request forgot password, then this token is generated like this
jwt.sign({ password, email }, secret, {expiresIn: "1d"})
When the user clicks the link and fills out the reset form. The password reset request is sent to the server and in the body contains the token from the url and the new password.
jwt.verify(req.body.token, secret)
Then I just checked if the hashed password in the database matches the one shown in the jwt payload. If it does, I will change the password in the database. If it doesnt,the one time link has been used already so I error (returns 400 error).
How to do this without storing password?
I would definitely refrain from sending the old password hash in the JWT. If someone were to get access to a bunch of these, they could use them to try to brute-force hack your authentication.
What I would do is have a separate table for password reset requests. So every time someone asks for a reset link
You create a new password reset request entry in your DB with the reset token
If there already was an existing password reset request for that user in your DB, you delete it
The user submits the reset request with their new password and the token
You query your password reset request table and verify that the token they provided matches the token in your DB (i.e. because you only keep the most up-to-date one, you know that it is the correct one)
You action the password change and delete the password reset request from the DB
Good luck!
People can try to crack a password hash even if it takes a long time:
https://security.stackexchange.com/questions/199494/how-to-crack-a-password-given-its-hash-and-its-possibilities
This makes your password hash sensitive which means you should not put it in your JWT token.
https://stackoverflow.com/questions/43496821/is-it-safe-to-store-sensitive-data-in-jwt-payload#:~:text=Ideally%20you%20should%20not%20store,by%20simply%20base64%20decoding%20it.
The time complexity/security risk depends on a lot of things(be sure you are salting your password).
This is a common problem with JWT tokens:
Here is a link to some solutions:
Invalidating JSON Web Tokens
One that was missed would be adding a password version(some number that increments when the password is changed) to your password. Then passing this version back in your token, instead of the password hash. Since you are already querying your database(to make sure the password is the same) you can just query to make sure the password version is the most recent version without any extra time complexity. If it is the same change the password. If it is not the same do not change the password.

Forgotten password -- A token that is only usable once but isn't stored

This is a question about generating a token for a user to reset his/her password, without storing said token in the database. This token would be part of a "reset password" URL sent by e-mail.
An answer posted by sudo explains that you can send the user a token with the following information
name
expiration date
hash(secret + user name + expiration date)
The problem with this method is that the user could change his password several times before the token expires. I think this is quite bad because it means that if the user accesses the URL from a shared computer that retains history, anyone could reset our user's password (even if just for a limited amount of time).
So my question is: is it possible to have a token that is usable only once, and that is not stored in the database?
Yes. An easy approach to getting a one-time use token you don't have to store or manage is to offload user management to a microservice like Stormpath where it takes care of all the user management for you-- password reset, password storage, user profiles, authentication, etc.
For password reset here's what it would look like:
User initiates password reset work on a web page
You make API call to stormpath with user's email address or username
Stormpath sends out reset email to user (your "from" address, custom HTML, etc) with a link + token. The reset token that is unique, one-time use, and expires if not used within 24 hours
User clicks on the link and lands on the reset page
You pull the token from the URL and check Stormpath for token verification
User submits new password
Stormpath sends out reset success message (your "from" address, custom HTML, etc)
You can build your own UIs in this flow or use an out of the box, customizale id site (id.mydomain.com) that Stormpath includes.
User never knows Stormpath exists and you don't have to manage or store any passwords or reset tokens.
Full Disclosure - I work at Stormpath
A possible solution is to use a slightly different token:
user name
expiration date
hash(secret + user name + password_hash + expiration date)
When the user accesses the password reset page for the first time, you can retrieve his password hash from the database, and check the hash. It matches, the user can reset his password.
When the user accesses the password reset page for the second time with the same link, it won't work: password_hash has changed, therefore the hash won't match.
But.... There is a problem if the user actually types his original password. In that case password_hash will stay unchanged and the token will remain valid. Because of this edge case, this solution isn't really viable.

Is this a secure way to handle cookies?

The scenario is a web app running with no ability to store information locally, such as sessions. So in order to provide state, here's what I'm thinking. The server has a list of users and SHA256(passwords + salt). When a user logs in, I would set a name cookie with the username and a key cookie with SHA256(SHA256(password + salt) . ip).
This would allow the server to compare the credentials without knowing the plain text password, it wouldn't expose the password in the client's cookie, and would safeguard the logged in credentials against being ex-filtrated into an attacker's system since it would only work on that one IP address.
The only drawback I can see is that there would be no way to enforce expiry. So it would basically be a lifetime cookie for that user/password/IP combination, or at least until the web app erases the cookie or the user changes his password.
you must not use password anywhere in cookie even if it is encrypted.
give every user an id and on every login you must:
1. Update login Time
2. Create unique session Id
3. set cookie with unique session id
now on every request to server
1. validate session cookie
2. Check login time and current server time.
it is just basic structure..

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

Node.js one session per user

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.

Resources