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 is one of the dependency for
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 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")
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 takes two inputs password hash and plaintext password and returns
True if hash matches actual hash of plaintext password else returns
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
generate_password_hashand store hashed version of password in database under column hashed_pwd.
check_password_hashby passing already hashed password for user from database and input password (plaintext) to test veracity of password.