Thought leadership from the most innovative tech companies, all in one place.

Implementing Flask login with hash password

A concise post that helps improve your authentication system


Flask is a minimalist Python framework, that possibilities high customization in your Design Patterns.

Assuming that our project already has your database connection already configured we will start with the following configuration:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from flask_login import LoginManager

app = Flask(__name__)

login_manager = LoginManager(app)

db = SQLAlchemy(app)
migrate = Migrate(app, db)

manager = Manager(app)
manager.add_command('db', MigrateCommand)

from app.models import tables, forms
from app.controllers import default

Our forms:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField
from wtforms.validators import DataRequired, Email

class LoginForm(FlaskForm):
    username = StringField("username", validators=[DataRequired()])
    password = PasswordField("password", validators=[DataRequired()])
    remember_me = BooleanField()

class RegisterForm(FlaskForm):
    username = StringField("username", validators=[DataRequired()])
    password = PasswordField("password", validators=[DataRequired()])
    name = StringField("name")
    email = StringField("email", validators=[DataRequired(), Email()])

our tables:

from app import db, login_manager
from flask_login import UserMixin
from import generate_password_hash, check_password_hash

def get_user(user_id):
    return User.query.get(user_id)

class User(db.Model, UserMixin):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password = db.Column(db.String(80))
    name = db.Column(db.String(80))
    email = db.Column(db.String(120), unique=True, nullable=False)

    def __init__(self, username, password, name, email):
        self.username = username
        self.password = generate_password_hash(password) = name = email

    def __repr__(self):
        return f'<User {self.username}>'

    def verify_password(self, pwd):
        return check_password_hash(self.password, pwd)

In the example above we are making the User model extends UserMixin so that we don’t need implement the functions is_authenticated, is_active, is_anonymous and get_id, necessary to implement of login.

In this case I use the native werkzeug lib of python to generate the hash in the User model constructor and the password verification with the check_password_hash method that returns true if password ok.

In controllers we have the functions (index, register, login e logout):

Register controller:


@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm()
    username =
    password =
    name =
    email =

    if form.validate_on_submit():
        user = User.query.filter_by(username=username).first()
        if not user:
            user = User(username, password, name, email)

        return redirect(url_for('login'))

        return render_template('register.html', form=form)

In Register controller, we use the data provided by the user to create a new user in the system.

Login controller:


@app.route("/login", methods=["GET", "POST"])
def login():
    form = LoginForm()
    username =
    password =

    if form.validate_on_submit():
        user = User.query.filter_by(username=username).first()

        if user and user.verify_password(password):
            flash("Usuário Logado!")
            flash("Login ivalido!")

    return render_template('login.html', form=form)

In Login controller, we use the username and password provided by the user to authenticate him with the flask_login method login_user and we send a message if the user is authenticated or not.

Index controller:


def index():
    return render_template('index.html')

In Index controller, the decorator @login_required was used so that only logged-in users can access the main page

Logout controller:


def logout():
    return redirect(url_for('login'))

In Logout controller, the current user logged-in in session is logged out with the flask_login method logout_user and a redirection is made to the login page.

You can see the full project in my github.

Continue Learning