In this article we will learn how to implement secure user authentication system using python werkzeug
. We will store secure passwords with salted hashes and later we will verify entered user password in plaintext against it's password hash to authenticate user.
Werkzeug is python library which contains lot of development and debugging tools for implementation of web application gateway interface(WSGI
) applications. The good part is you can use this system not only for your web applications but also for standalone python applications like desktop apps, scripts, mobile apps and so on.
Install Werkzeug with pip
pip install werkzeug
Skip this step if you are using flask
because flask will automatically install werkzeug
as werkzeug
is one of the dependency for flask
.
Understanding Secure Passwords
Before we delve into the code it's good idea to zero in on what is secure password storage.
- Passwords will not be stored as plaintext in database.
- Password will be stored as hash which is irreversible to plaintext. (one way hash).
- With given hash attacker cannot guess plaintext.
- Each user password will be hashed with salt to mitigate rainbow table attacks; Just in case if database got compromised.
Werkzeug Security Functions
There are various security functions available in the werkzeug.security
but we are interested in generate_password_hash
and check_password_hash
.
generate_password_hash
generate_password_hash
takes plaintext password, hashing method and salt length as an input to produce hashed password. By default it produces salt string with length 8.
from werkzeug.security import generate_password_hash
print generate_password_hash("P1ain-text-user-passw@rd", "sha256")
sha256$lTsEjTVv$c794661e2c734903267fbc39205e53eca607f9ca2f85812c95020fe8afb3bc62
Note that output string contains hashing method, salt and hashed password concatenated with the $
(dolor). Store hashed string as it is in your database under column hashed_password.
check_password_hash
check_password_hash
takes two inputs password hash and plaintext password and returns True
if hash matches actual hash of plaintext password else returns False
from werkzeug.security import check_password_hash
print check_password_hash("sha256$lTsEjTVv$c794661e2c734903267fbc39205e53eca607f9ca2f85812c95020fe8afb3bc62", "P1ain-text-user-passw@rd")
>> True
from werkzeug.security import check_password_hash
print check_password_hash("sha256$lTsEjTVv$c794661e2c734903267fbc39205e53eca607f9ca2f85812c95020fe8afb3bc62", "wrong-passw@rd")
>> False
Conclusion
generate_password_hash
and store hashed version of password in database under column hashed_pwd.check_password_hash
by passing already hashed password for user from database and input password (plaintext) to test veracity of password.