password reset with jwt structure - javascript

I'm trying to write the password reset part of my authentication app. I chose to use JWT, node.js and express where I use the following logic: first, the user enters their email and a token is generated and sent to the user's mail in a password reset link. second, when the user presses the link a function is set to check if the token is correct and if it's still valid and third i have a function to save the new password to the database.
What I'm uncertain about is the second step where the token is supposed to be checked. Some tutorials say that you're supposed to save the token to your database and then compare the token in the link to the token in the database. But isn't the point with using JWT to not save anything to the database as reference? Shouldn't I just use jwt.verify to get the information saved in the token and then check for the user in the database and if it's still active?
Is this the correct way of using JWT? Or would you recommend me to use session instead of JWT?

There's a good suggestion in this answer. You can use some hash of your currently stored password value as part of the password reset JWT.
So the payload might contain { sub: user_id, exp: "now + 10 minutes", purpose: "password_reset", key: hash(hashed_password_from_db).substr(0, 6) }. This token can only be used successfully once.

There is a simple flaw in the use of JWT for reset password implementation.
From your current implementation, A user can generate the reset password link multiple times. So a user can have many active reset token in a given time.
Yes, JWT statelessness can be adopted, but it is not efficient in this case as you can have multiple tokens which can be used to reset the password even after the user has reset the password(depending on your approach).
I work in an organisation where testing and security is paramount. Your implementation would not be allowed.
The rule is that only one reset password link can be active at a time.
So JWT token is not the best option for us.
So what I do is to generate a random token saved in the DB(also with the current time). This token is to identify the user and, the time is to validate that the user is resetting withing a given time.
While the token is active, if a user decides to generate the token again, the former token is made inactive before a new one is generated.
The advantage of this method is that you can only have one active token at a time.
Lastly, JWT should be used if you don't mind a user having multiple active tokens/links at a time.

Related

How to build "Selectable Keep Login" function by Cookie/JWT

I'm using Node(axios,pinia)+Vue3 as frontEnd,and node(express,bcrypt,jsonwebtoken)+MongoDB as BackEnd to build a SPA web.
I use JWT for login authentication and save at localstorage.
Now it only can keep login.
Hoping have Selectable "Keep Login" function like some forum usually have.
(After closing browser/shotdown will need to login again.)
I don't use sessionStorage for this website user often open new tab.Some cross tab problem bother me and I thought cookie might got better solution.
I can imagine only "Always login"/"temp login" can be done likes. But with selectable I can't thought a simple way to apply it.
Like now I'm thought still use LocalStorage(LS) for Vue to run,but also have Session Cookie(as Cookie)(Not sure the name but the cookiewill be deleted when all webs closed).
Keep login need no change for me.If set to temp login, then the setting will be save to JWT,all front/back could know.
Use cache as signal for closing browser,if (temp login)&&(no cookie){clear LS}.
However I wonder the localStorage can be extract so the func will not safty enough? Then a school computer will be disaster
I'm new to cookie/session,and want to know any better way for safty/efficent. I will prevent XSS.
It would be wonderful to have your experienct/Idea!
Poor language and consult at here first,If any describe not clear/too detail please tell me,I will try to edit it, thanks!
The use of JWT is below:
BackEnd use bcrypt verify user password and response a JWT(with userID for db to find,also save to user login record DB) and other basic user info.
Some response data like JWT,basic userinfo will be save in localstorage to let Vue decide display login/admin/different page.
When user send a request(some login-action), JWT will also be send as BearToken to bo verified by backEnd that JWT was record in that user login record.
So JWT is the only security key,the user's login record should have same JWT.
Because it save in localstorage,user must logout!(Despite I can set some limit time.)

How to implement "forgot/reset password" feature properly in Node.js? (Using one time token)

I am implementing a forgot/reset password functionality in a Node.js app using NestJs.
That is the general flow:
A user types in his email in a "forgot password" form and submits the request
The server generates a jwt token with the user's ID as the payload, then sends an email with the token as the link to reset the password (example: GET: example.com/reset/generated_jwt_token)
User clicks the link from his email, the reset password page is rendered, he fills the form with the new password and submits the form with the password as the body (example: POST: example.com/reset/generated_jwt_token)
Server verifies the token (that is not expired + user ID from payload exists in the DB) and updates the password.
The main problem with this approach is that the jwt token can be used unlimited amount of times to reset the password (until it expires after X minutes).
Is there a way to solve this? some say to put the current password's hash as the payload since it will be changed anyway and will guarantee 1 time use, but I'm not a fan of this method.
EDIT: Another approach i encountered is creating a blacklist collection in the DB of jwt token that cannot be used more than once. Or using a cache in redis the same way, but it seems not very scalable.
When a token is generated, you could save it (or something unique embedded inside it) into the database under that user. Then, the server verifies the token:
(1) when the link from the reset email is clicked
(2) when the user submits the reset password page
by checking that the token is the same as the one for that user in the database.
Also, when the user successfully changes their password, clear the token from the database so it can't be used again.
I agree with the (accepted) answer of #CertainPerformance.
I would like to add - Consider using authentication-flows-js. You will not have to worry about the implementation at all!
It is a module that answers most flows - authentication, registration, forgot-password, change password etc., and it is secured enough so applications can use it without the fear that it will be easily hacked.
From an article I wrote:
Forgot Password
The user enters their email in the forgot password
form, and clicks submit. The server (AFM) verifies the account exists
and is not locked. If it is locked, AFM throws an error. Otherwise, an
email is sent to the user with a token. That token is stored in the DB
in the same row/document/record of the user.
Read the full article with more explanations here.

How to make JWT token based link as one time use link for Reset Password and Email Verification functionality

1. What I have done till now
I added reset password functionality in my project in which user gets the link in their respective email. I used user's hashed password as its secret key to make the link ONE TIME USE. So if the user change his password once than the hash changes and also the secret key making the token verification invalid which in turns makes the the link ONE TIME USE. As I used user's hashed password as its secret key I also have to pass user's _id with the token in the link so that at the time of verifying the token first I fetch the user's password hash with the help of the user's _id that I passed with the token in the link.
2. What I want to do
Now it's time to add email verification functionality to my project and I am not getting any idea of how to make the verification link as one time link. And what if the users request multiple times for the email verification and I generate that many link and send it to the user's respective email.
3. I thought of doing this
I thought of creating a database for email verification and insert the user_Id and token to that database each time the user requests for the verification and once the user click any of the requested links I make the user verified and delete all the token associated to the user's user_Id so that when the user clicks any of the link or the same link again the email is already verified and token is deleted so I can response "Invalid Link or Request" to the user.
If the no. 3 is a legit mechanism I will implement same to no. 1
If the above mechanism is legit and good to go I would like to implement the same for my password reset functionality so that I no need to use user's password hash as the secret key and also not pass the user's _id in the link
Please also give suggestions if these both functionality can be done in a different way

Saving OAuth2 access tokens for sessionless authentication

I set up a sessionless app that uses OAuth2 password grant authentication. When a user logs into my app with a username and password I save the access token in sessionStorage which is valid for 30 minutes. I also save a refresh token in sessionStorage in case I need to extend the session longer than 30 minutes. The refresh token is valid for 30 days.
If the 'remember me' checkbox is selected on login I save the access and refresh tokens in localStorage so they will persist as long as the refresh token is valid.
Both of these seem to work fine except for a couple of issues:
If the browser is left open and the user doesn't log out the session could potentially last for 30 days.
sessionsStorage doesn't persist between windows/tabs so if the user opens a new window they need to log in again. This is not an issue when the 'remember me' checkbox is selected since localStorage does persist between windows.
I think using refresh tokens is not safe for JavaScript applications - you need to access the /token endpoint and authenticate using the application's secret. But the secret gets public in such applications.
I would prefer the OAuth2 implicit flow and getting new token from the /auth endpoint with prompt=none parameter (from OpenID Connect). But with the implicit flow, you would either need to get a longer living ID token (and ask for an access token with the ID token later) or to implement the "remember me" at the OAuth2 (better option - can be used by any application). That would also solve the problem #2 with passing tokens between tabs.
By the "session" you mean using the refresh token to generate access tokens for 30 days? If that's a problem, you can implement some activity detector which would log the user out if there is no activity for e.g. 30 minutes.
It's possible to use the localStorage as a kind of message passing service, so you can keep the tokens in the sessionStorage, but a new tab can use the localStorage to request the token from existing tabs. For more info see http://www.codediesel.com/javascript/sharing-messages-and-data-across-windows-using-localstorage/
Code example from the linked article:
function eventListener(e) {
if (e.key == 'storage-event') {
output.innerHTML = e.newValue;
}
}
function triggerEvent() {
localStorage.setItem('storage-event', this.value);
}
window.addEventListener("storage", eventListener, true);
data.addEventListener("keyup", triggerEvent, true);
The workflow would be like this:
New tab is opened and writes an arbitrary value to the localStorage with a key indicating that it needs a token. The key can be "newTabOpened". The new tab starts listening to changes of another key "oauth2token".
The existing tab listens to the changes of the "newTabOpened" key and as a reaction, it writes its token value under the "oauth2token" key.
The new tab reads the token and removes it from the localStorage.

Disable multiple user login for web based application

I'm creating a web based application that requires people to register and login for access to certain pages.
I want to stop users from giving out their username/password to other people by denying access to more than one person using the same username at the
same time.
Don't know if its a great solution but you can keep a bit in users table and set it to 1 when user is logged in. And check it before login, if its set don't allow more logins by other users. On logout function unset this bit.
In spring security, we can able to manage user login like this,
<session-management>
<concurrency-control max-sessions="1"/>
</session-management>
So when the time user logged in, you will gonna set some session values, If one more user going to login using existing user logged in ID and password, before going to login condition, check those parameters in the back end. You can able to prevent user login from multiple times for the Same userLogin and Password.
You can use either database or distributed cache.
I prefer using database ( User_ID, SessionKey, LoginTime, Logout time)
After login, you have to record entry in database/cache with a unique session id. When login is attempted with same credentials, update existing entry with logout time and create new entry with recent login time
e.g. When you login with John,
the entry in table is like 'John','1020edf1','29-06-2015 00:10:00',null.
When second login comes after 10 minutes,
The entries in table will be like this
'John','1020edf1','29-06-2015 00:10:00','29-06-2015 00:20:00'
'John','10asdf21','29-06-2015 00:20:00','null'
Form your application, you can have reaper thread mechanism, which will remove inactive sessions if user tries to logout from the application.
Here session key is unique session id generated by application server.

Categories