PASSWORD RESET LINK IN FLASK
Password reset is a common feature in websites that allows users to reset their password if they forget it or feel it has been compromised. In this article, we will learn how to send a password reset link to a user’s registered email using Flask.
Steps to follow:
- We will add a “Forgot password” link on the login page.
- Clicking on the link will take the user to a page where they can enter the username associated with their account.
- A reset link will be sent to the user’s registered email.
- The user can click on the reset link to go to the password reset page where they can enter their new password.
- The user can now log in using their new password.
Here is the code for the login page (login.html):
<form method="post" action="/dashboard">
<div class="container" style="max-width:50%;margin-left: 220px;" >
<div class="mb-3 px-10">
<input type="text" class="form-control" id="uname" name="uname" placeholder="Username">
</div>
<div class="mb-3">
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
</div>
<a href="{{url_for('pass_reset')}}" style="color:#006990;"><u> Forgot Password?</u></a>
<center>
<div class="mb-3">
<input type="submit" class="btn btn-outline-primary" value="Login"/>
</div>
<pre>Don't have an account? <a href="{{url_for('registeration')}}"><u>Sign Up Here</u></a></pre>
</center>
</div>
</form>
The highlighted code above is for the “Forgot Password” link. Clicking on this link will take the user to the password reset page.
Here is the Flask function for rendering the password reset page:
@app.route('/pass_reset')
def pass_reset():
return render_template('password_reset.html',params=params)
Next, we need to create a function that will check if the user exists and send the password reset link to the user’s email:
@app.route('/reset_password',methods=['GET','POST'])
def reset_link():
try:
confirm_serializer = URLSafeTimedSerializer(app.config['SECRET_KEY'])
uname = request.form.get('uname')
token = confirm_serializer.dumps(uname,salt='reset_pass')
email=New_user.query.filter_by(username=uname).first().email
msg = Message('Password Reset', sender=params['gmail_user'], recipients=[email])
link = url_for('reset_password', token=token,_external=True)
msg.html=render_template('reset_template.html',link=link,username=uname)
print(token)
mail.send(msg)
flash('Password Reset link sent to '+email)
return redirect(url_for('dashboard'))
except AttributeError:
flash('Invalid Username')
return redirect(url_for('pass_reset'))
Let’s understand how this code works! In the above code, we use the URLSafeTimedSerializer()
the method from the Itsdangerous package to generate a unique reset token based on the username provided by the user. This token contains a timestamp that acts as an expiration date; after that, it will be useless, and the user will need a new token. The Serializer
class provides dumps/loads
methods, which serialize the object to a string and then sign it. The loads
the method is used to generate the token and the dumps
the method is used to separate the token from our URL, which we will use later in this tutorial.
Then, we fetch the username from our form and store it in a variable for future use. Suppose we have a confirmation link on our system that can confirm a user account and a reset link that can reset the password. If we sign both links using the username, a user could reuse the variable part of the URL from the confirmation link to reset the password. To prevent this, we can put more information in the URL that we sign (like the intention: reset or confirmation). Salt can be used to help our program differentiate between these two. Even if the Salt is disclosed, we don’t need to worry because without the secret key, it does not help an attacker. Using the username and Salt, a token is generated. We have created a function (which we will discuss in the next step) that will generate and validate the link. Finally, we will attach this link to our email body and send it to the user.
Flask function to reset the password and update it in our database.
To reset the password and update it in the database, we can use the following Flask function:
@app.route('/reset_password/<token>', methods=['GET', 'POST'])
def reset_password(token):
try:
confirm_serializer = URLSafeTimedSerializer(app.config['SECRET_KEY'])
print(token)
uname = confirm_serializer.loads(token, salt='reset_pass', max_age=3600)
print(uname)
user = New_user.query.filter_by(username=uname).first()
except:
flash('The confirmation link is invalid or has expired.')
if request.method == 'POST':
passw = request.form.get('pass') # password
cpass = request.form.get('cpass') # confirm password
if passw == cpass:
encrypt_pass = bcrypt.generate_password_hash(passw) # encrypt the password
user.password = encrypt_pass
db.session.commit()
flash('Password updated successfully!')
return redirect(url_for('dashboard'))
return render_template('new_pass.html', params=params, token=token)
This function is called when the user clicks on the password reset URL that we send them. It takes them token
as input and tries to load the uname
using the URLSafeTimedSerializer
class of the Itsdangerous package. The max_age
parameter specifies the maximum age of the token in seconds, after which it becomes invalid.
Next, we fetch the user object from the database using the uname
retrieved from the token. If the token is invalid or has expired, we flash an error message.
If the request method is POST
, it means the user has submitted a new password. We get the password and confirm the password from the form, and if they match, we generate a hashed password using the generate_password_hash()
function of the bcrypt
package. We then update the user's password in the database and commit the changes. Finally, we flash a success message and redirect the user to the dashboard page.
If the request method is GET
, we render the new_pass.html
template with the params
and token
variables passed to it. The params
the variable contains any additional parameters that we want to pass to the template and the token
the variable contains the token that we received in the URL.
In this way, we can reset the user’s password and update it in the database using Flask.
Any suggestions and comments would be greatly appreciated. If you found this article helpful, please like and share it with others. Don’t forget to follow me to stay up-to-date on my latest articles. Thank you for taking the time to read this!