In web applications, user authentication (verifying user identity) and permission control (restricting actions based on user roles) are core functionalities. As a lightweight web framework, Flask can easily implement these features using the Flask-Login extension. This article will guide beginners through the simplest steps to understand user login, authentication state maintenance, and basic permission control with Flask-Login.
1. Preparation: Install Required Libraries¶
First, install Flask and Flask-Login. If storing user data, also install Flask-SQLAlchemy (database ORM) and Werkzeug (password hashing). Run in the terminal:
pip install flask flask-login flask-sqlalchemy werkzeug
2. Core Concept: Role of Flask-Login¶
Flask-Login primarily addresses two issues:
1. Session Management: Automatically maintains user login state (e.g., “Remember Me” functionality, automatic logout on timeout).
2. Permission Verification: Controls route access using decorators (e.g., restricting access to logged-in users only).
3. Step 1: Configure the App and User Model¶
3.1 Initialize the App and Database¶
Create app.py and initialize the Flask app and database:
from flask import Flask, render_template, redirect, url_for, request, flash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
# Initialize Flask app
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key-here' # Use a random string in production
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' # SQLite database
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # Disable unnecessary tracking
# Initialize database and LoginManager
db = SQLAlchemy(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login' # Redirect unauthenticated users here
3.2 Define the User Model¶
Create a User class inheriting from UserMixin (implements default Flask-Login methods) to store user data:
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True) # User ID
username = db.Column(db.String(80), unique=True, nullable=False) # Username
password_hash = db.Column(db.String(120), nullable=False) # Hashed password (not plaintext)
# Hash password before storage
def set_password(self, password):
self.password_hash = generate_password_hash(password)
# Verify password during login
def check_password(self, password):
return check_password_hash(self.password_hash, password)
3.3 Create Database Tables¶
In the terminal, use Python to create database tables:
>>> from app import app, db
>>> with app.app_context():
... db.create_all() # Creates table structures
4. Step 2: Configure User Loading and Authentication¶
4.1 User Loading Function¶
Flask-Login requires a function to load users from the session. Register it with @login_manager.user_loader:
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id)) # Fetch user by ID from the database
- Purpose: After login, Flask-Login uses this function to load user data into the session.
5. Step 3: Implement Login and Logout¶
5.1 Login Page and Form¶
Create templates/login.html for the login form:
<!-- templates/login.html -->
<h1>Login</h1>
{% if error %}
<p style="color: red;">{{ error }}</p>
{% endif %}
<form method="POST">
<input type="text" name="username" placeholder="Username" required><br><br>
<input type="password" name="password" placeholder="Password" required><br><br>
<button type="submit">Login</button>
</form>
5.2 Login Route¶
Add login logic to app.py:
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user = User.query.filter_by(username=username).first()
# Verify credentials
if user and user.check_password(password):
login_user(user) # Maintain login state (session)
return redirect(url_for('dashboard')) # Redirect to dashboard
else:
return render_template('login.html', error='Invalid username or password')
return render_template('login.html') # Show form for GET requests
5.3 Logout Route¶
Use logout_user() to clear the session:
@app.route('/logout')
@login_required # Only accessible to logged-in users
def logout():
logout_user() # Clear session
return redirect(url_for('login')) # Redirect to login page
6. Step 4: Permission Control¶
6.1 Protect Routes (Authenticated Users Only)¶
Use @login_required to restrict access to logged-in users:
@app.route('/dashboard')
@login_required # Redirects unauthenticated users to login_view
def dashboard():
return f"Welcome back, {current_user.username}!" # current_user = active user
6.2 Role-Based Access Control (Advanced)¶
Add a role field to the user model for granular permissions:
class User(UserMixin, db.Model):
# Existing fields...
role = db.Column(db.String(20), default='user') # e.g., 'user' or 'admin'
# Restrict admin-only routes
@app.route('/admin')
@login_required
def admin_panel():
if current_user.role != 'admin': # Check user role
flash('You do not have admin access!')
return redirect(url_for('dashboard'))
return "Admin Dashboard"
7. Key Notes¶
- Password Security: Always hash passwords with
Werkzeug(never store plaintext passwords):
user.set_password(password) # Hash before storage
user.check_password(password) # Verify during login
- Session Security: Use a random, complex
SECRET_KEY(store in environment variables in production). - User Loading: The
@login_manager.user_loaderfunction must return the correct user object. - Current User:
current_userprovides access to the active user’s data (e.g.,current_user.username).
8. Summary¶
With Flask-Login, we implemented:
- Automatic session management for login state.
- Route protection via @login_required.
- Basic role-based access control (via user roles).
Next steps: Add “Remember Me” functionality, password reset, or OAuth for third-party logins.
Full Code Example¶
app.py¶
# [All previous code except imports]
if __name__ == '__main__':
with app.app_context():
db.create_all() # Create tables on first run
app.run(debug=True)
templates/login.html¶
<!DOCTYPE html>
<html>
<head><title>Login</title></head>
<body>
<h1>Login</h1>
{% if error %}
<p style="color: red;">{{ error }}</p>
{% endif %}
<form method="POST">
<input type="text" name="username" placeholder="Username" required><br><br>
<input type="password" name="password" placeholder="Password" required><br><br>
<button type="submit">Login</button>
</form>
</body>
</html>
Run python app.py and visit http://localhost:5000/login to test the login flow!