How to Implement User Authentication in Python Flask – A Step-by-Step Guide to Setting Up Flask Login

Posted by


In this tutorial, we will be going over how to implement authentication in a Flask application using the Flask-Login extension. Flask-Login provides user session management, handling user login and logout, and protecting routes that require authentication.

To get started, make sure you have Flask installed. You can install Flask using pip:

pip install Flask

Next, install Flask-Login:

pip install Flask-Login

Now let’s create a new Flask app and configure Flask-Login.

from flask import Flask, render_template, redirect, url_for
from flask_login import LoginManager

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key_here'

login_manager = LoginManager()
login_manager.init_app(app)

In the code above, we import Flask, render_template, redirect, and url_for from the flask module. We also import LoginManager from the flask_login module.

We create a new instance of the Flask class and set a secret key in the app configuration. The secret key is used to secure session data.

We create an instance of the LoginManager class and initialize it with our Flask app.

Next, we need to create a User class that represents a user in our application.

from flask_login import UserMixin

class User(UserMixin):
    def __init__(self, id):
        self.id = id

The User class above inherits from UserMixin, which provides default implementations for the methods required by Flask-Login.

Now let’s set up a basic login route that will allow users to log in to our application.

@app.route('/login', methods=['GET', 'POST'])
def login():
    user = User(id=1)  # In a real application, authenticate the user
    login_user(user)
    return redirect(url_for('index'))

In the code above, we define a /login route that accepts GET and POST requests. We create a new instance of the User class and log the user in using the login_user function provided by Flask-Login. Finally, we redirect the user to the index route.

Now let’s create a basic logout route that will allow users to log out of our application.

@app.route('/logout')
def logout():
    logout_user()
    return redirect(url_for('index'))

In the code above, we define a /logout route that logs the user out using the logout_user function provided by Flask-Login. Finally, we redirect the user to the index route.

Next, we will create a before_request function that will ensure that the user is logged in before accessing certain routes.

@app.before_request
def before_request():
    if not current_user.is_authenticated and request.endpoint != 'login':
        return redirect(url_for('login'))

In the code above, we define a before_request function that checks if the current user is authenticated and if the endpoint being accessed is not the login route. If the user is not authenticated and the endpoint is not the login route, we redirect the user to the login route.

Finally, let’s create a simple index route that will display a welcome message to authenticated users.

@app.route('/')
def index():
    return 'Hello, {}!'.format(current_user.id)

In the code above, we define an index route that displays a welcome message with the current user’s ID.

That’s it! You now have a basic Flask application that implements authentication using Flask-Login. You can expand on this by adding user registration, password hashing, and more advanced authentication features. Flask-Login documentation is a great resource for more information and examples: https://flask-login.readthedocs.io/en/latest/

0 0 votes
Article Rating
42 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
@ArpanNeupaneProductions
1 month ago

For people wondering where the code is in this video, you can find it here: https://github.com/arpanneupane19/Python-Flask-Authentication-Tutorial

@harrisonlong644
1 month ago

IF YOU EVER EXPERIENCE ISSUES WITH LOGIN EITHER KEEPING YOU LOGGED IN OR NOT LETTING YOU LOG IN OR JUST MIS-MANAGING THE LOGINS IN ANYWAY:

you only need this line of code once, when running db.create_all()

app.app_context().push()

once you have run db.create_all() you can comment it out.

@JahnaviMaredla
1 month ago

I dont know why but the user table is not getting created and when i do the .tables i am not getting the user table just blank and next line of sqlite> pls somebody help with this why its happening and how to resolve it

@eternalsunshinev29
1 month ago

hello i keep having this issue: RuntimeError: Either 'SQLALCHEMY_DATABASE_URI' or 'SQLALCHEMY_BINDS' must be set.
i've checked multiple times and idk whats wrong with my code

@qq587
1 month ago

3:30 i get an import error

@bowencl5157
1 month ago

I got struct on the app context. the error was something like use app.app_context() or with app.app_context(): db.create_all(). I had to include app.app_context().push() in the app.py file and also had to use basedir = os.path.abspath(os.path.dirname(__file__)) with app.config['SQLALCHEMY_DATABASE_URI'] =

'sqlite:///' + os.path.join(basedir, 'database.db') in order to get you code to work but I'm good now! thanks man

@Ashleycashmoney
1 month ago

Goated tutorial

@johannahigbea4521
1 month ago

Great video, love that you go step by step and explain why you are adding the code. I know you are using a MAC, but wanted to ask if you tested this full tutorial in a Windows system. It seems that many users are having issues with the DB part of the tutorial and think it might be good for you to provide more insight and answers on the issues that may occur in a Windows environment. When I run 'from app import db', it creates a folder called instance, therefore, when I run db.create_all() I get an error, because there is no database.db in the instance folder.. Can you please try this exact tutorial in Windows and update the video to include the differences? Thank you!

@vidgagames474
1 month ago

24:03

@selama16
1 month ago

Thank you

@MuhammadMuhsinYahya
1 month ago

Very good explanation and well presented, thank you. But how about the styling the page

@prezlamen
1 month ago

Use minimum font size 20 for youtube this is impossible to see

@cupid4614
1 month ago

thanks bro

@TomTwyman
1 month ago

Wow! Great video! you just saved me a TON of time – new to Flask, and I was busy trying to piece together everything I needed for a simple authentication system, and you nailed it in one! Thanks a ton! I do have a question about some of the items in your requirements.txt – you have some items in there that aren't explicitly called out in the video – cffi, asgiref, dnspython, etc. Can you expand on why you included them?

@AndreKaiqueDellIsola
1 month ago

14:08
from app import app, db

with app.app_context():

db.create_all()

@AndreKaiqueDellIsola
1 month ago

13:59

from flask import Flask, render_template

from flask_login import UserMixin

from flask_sqlalchemy import SQLAlchemy

from flask_wtf import FlaskForm

from wtforms import StringField, PasswordField, SubmitField

from wtforms.validators import InputRequired, Length

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'

app.config['SECRET_KEY'] = 'thisisasecretkey'

db = SQLAlchemy(app)

class User(db.Model, UserMixin):

id = db.Column(db.Integer, primary_key=True)

username = db.Column(db.String(20), nullable=False, unique=True)

email = db.Column(db.String(150), nullable=False, unique=True)

password = db.Column(db.String(80), nullable=False)

class RegisterForm(FlaskForm):

username = StringField('Username', validators=[InputRequired(), Length(min=4, max=20)], render_kw={"placeholder": "Username"})

password = PasswordField('Password', validators=[InputRequired(), Length(min=4, max=20)], render_kw={"placeholder": "Password"})

submit = SubmitField('Register')

@app.route('/')

def home():

return render_template('home.html')

@app.route('/login')

def login():

return render_template('login.html')

@app.route('/register')

def register():

form = RegisterForm()

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

if _name_ == '__main__':

app.run(debug=True)

@AndreKaiqueDellIsola
1 month ago

15:38

O erro "No module named 'flask'" indica que o módulo Flask não está instalado no seu ambiente Python atual. Para resolver isso, siga os passos abaixo:

### Passos para instalar o Flask

1. *Criar um ambiente virtual* (se ainda não tiver criado):

“`bash

python -m venv venv

“`

2. **Ativar o ambiente virtual**:

– No Windows:

“`bash

venvScriptsactivate

“`

– No macOS/Linux:

“`bash

source venv/bin/activate

“`

3. **Instalar Flask e outras dependências**:

“`bash

pip install flask flask_sqlalchemy flask_login flask_wtf

“`

4. **Verificar a instalação**:

– Você pode verificar se o Flask foi instalado corretamente executando:

“`bash

pip list

“`

– Certifique-se de que `flask`, `flask_sqlalchemy`, `flask_login` e `flask_wtf` estejam listados.

### Reestruturando o projeto

Certifique-se de que a estrutura do seu projeto está correta. Aqui está um exemplo:

“`

my_flask_app/



├── app.py

├── models.py

├── forms.py

├── templates/

│ ├── login.html

│ ├── register.html

│ └── home.html

└── static/

└── styles.css

“`

### Arquivo `app.py`

“`python

from flask import Flask, render_template, redirect, url_for, flash

from flask_sqlalchemy import SQLAlchemy

from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user

from forms import LoginForm, RegisterForm

from models import User, db

app = Flask(__name__)

app.config['SECRET_KEY'] = 'your_secret_key'

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'

db.init_app(app)

login_manager = LoginManager(app)

login_manager.login_view = 'login'

@login_manager.user_loader

def load_user(user_id):

return User.query.get(int(user_id))

@app.route('/')

@app.route('/home')

def home():

return render_template('home.html')

@app.route('/login', methods=['GET', 'POST'])

def login():

form = LoginForm()

if form.validate_on_submit():

user = User.query.filter_by(email=form.email.data).first()

if user and user.check_password(form.password.data):

login_user(user, remember=form.remember.data)

return redirect(url_for('home'))

else:

flash('Login Unsuccessful. Please check email and password', 'danger')

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

@app.route('/register', methods=['GET', 'POST'])

def register():

form = RegisterForm()

if form.validate_on_submit():

user = User(email=form.email.data, username=form.username.data)

user.set_password(form.password.data)

db.session.add(user)

db.session.commit()

flash('Your account has been created!', 'success')

return redirect(url_for('login'))

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

@app.route('/logout')

@login_required

def logout():

logout_user()

return redirect(url_for('home'))

if _name_ == '__main__':

with app.app_context():

db.create_all()

app.run(debug=True)

“`

### Arquivo `models.py`

“`python

from flask_sqlalchemy import SQLAlchemy

from flask_login import UserMixin

from werkzeug.security import generate_password_hash, check_password_hash

db = SQLAlchemy()

class User(db.Model, UserMixin):

id = db.Column(db.Integer, primary_key=True)

username = db.Column(db.String(150), nullable=False, unique=True)

email = db.Column(db.String(150), nullable=False, unique=True)

password_hash = db.Column(db.String(256), nullable=False)

def set_password(self, password):

self.password_hash = generate_password_hash(password)

def check_password(self, password):

return check_password_hash(self.password_hash, password)

“`

### Arquivo `forms.py`

“`python

from flask_wtf import FlaskForm

from wtforms import StringField, PasswordField, SubmitField, BooleanField

from wtforms.validators import DataRequired, Length, Email, EqualTo

class LoginForm(FlaskForm):

email = StringField('Email', validators=[DataRequired(), Email()])

password = PasswordField('Password', validators=[DataRequired()])

remember = BooleanField('Remember Me')

submit = SubmitField('Login')

class RegisterForm(FlaskForm):

username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])

email = StringField('Email', validators=[DataRequired(), Email()])

password = PasswordField('Password', validators=[DataRequired()])

confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])

submit = SubmitField('Sign Up')

“`

### Verifique se todos os arquivos estão no mesmo diretório e executando o servidor Flask

Certifique-se de que todos os arquivos estão no diretório correto e execute o servidor Flask novamente. Navegue até o diretório do seu projeto e execute:

“`bash

flask run

“`

Se o Flask ainda não estiver encontrado, tente instalar o Flask explicitamente novamente e garantir que você está ativando o ambiente virtual corretamente:

“`bash

pip install flask

“`

Certifique-se de que o comando `pip list` inclui `flask` na lista de pacotes instalados.

@SATHISHKUMAR-hg5et
1 month ago

hi im getting this error TypeError: FlaskForm.validate_on_submit() missing 1 required positional argument: 'self' how to resolve it

@saran_freaky
1 month ago

madan bro random room match epo ???

@Quaght
1 month ago

Say I have 5 web pages but only one of them requires a login. Do I add @login_required only to the route to that page?