When building web applications with Flask, Extra resources developers enjoy complete architectural freedom. You can choose your database ORM, structure your folders however you like, and handpick individual extensions for routing, forms, and email handling. However, this flexibility introduces a major responsibility when it comes to security.
Implementing user authentication, role-based access control, password hashing, account confirmations, password resets, multi-factor authentication, and protection against common web vulnerabilities from scratch is time-consuming and fraught with risk. Reinventing the security wheel often leads to subtle implementation flaws that compromise user data.
Enter Flask-Security-Too. As the modern, actively maintained successor to the original Flask-Security library, Flask-Security-Too provides a comprehensive, batteries-included security layer designed to drop seamlessly into any Flask application.
This comprehensive guide explores everything you need to know to master Flask-Security-Too, from core authentication workflows and multi-factor integration to advanced authorization and production best practices.
What is Flask-Security-Too?
Flask-Security-Too is a powerful Flask extension that quickly adds common security mechanisms to your web applications. Rather than forcing developers to manually coordinate separate extensions for login sessions (Flask-Login), form validation (Flask-WTF), password hashing (Werkzeug), and role management, Flask-Security-Too unifies these features into a single, cohesive framework.
+-----------------------------------+
| Flask App |
| (Incoming HTTP Request) |
+-----------------+-----------------+
|
v
+-----------------+-----------------+
| Flask-Security-Too |
| (Unified Auth & Security Suite) |
+-----------------+-----------------+
|
+----------------------+----------------------+
| | |
+---------v---------+ +---------v---------+ +---------v---------+
| Session / | | Role & Permission | | MFA, WebAuthn & |
| Token Auth | | Access Control | | Social Login |
+-------------------+ +-------------------+ +-------------------+
Key features provided out of the box include:
- Session-based and Token-based Authentication: Support for standard cookie sessions, HTTP Basic Auth, token auth, and JSON Web Tokens (JWT) / Refresh Tokens.
- User Registration and Account Activation: Optional signup workflows with email confirmation tokens.
- Role-Based Access Control (RBAC): Granular permission checking using roles assigned to users.
- Password Management: Secure password hashing, complexity validation rules, reset tokens, and change-password workflows.
- Multi-Factor Authentication (MFA): Built-in support for authenticator apps (TOTP), SMS, email codes, recovery codes, and WebAuthn/Passkeys.
- Social Login (OAuth): Integrated support for external identity providers via Authlib.
Setting Up Flask-Security-Too
Integrating Flask-Security-Too into a modern Flask application using Flask-SQLAlchemy for data persistence is straightforward.
Step 1: Installation
Install Flask-Security-Too along with SQLAlchemy support using pip:
pip install Flask-Security-Too[fsqla]
Step 2: Configuring the Application and Models
Flask-Security-Too requires specific configuration keys (such as a secure SECRET_KEY and a salt for cryptographic hashing) and expects standard User and Role data models.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin
db = SQLAlchemy()
# Define models for Role and User
roles_users = db.Table(
'roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))
)
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
class User(db.Model, UserMixin):
id = db.Column(db.Integer(), primary_key=True)
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'super-secret-key-change-in-production'
app.config['SECURITY_PASSWORD_SALT'] = 'super-password-salt-change-in-production'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
# Configure token and session settings
app.config['SECURITY_REGISTERABLE'] = True
app.config['SECURITY_CONFIRMABLE'] = True
app.config['SECURITY_SEND_REGISTER_EMAIL'] = True
db.init_app(app)
# Setup Flask-Security datastore
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
with app.app_context():
db.create_all()
return app
Core Security Workflows
1. Protecting Views and Enforcing Roles
Flask-Security-Too provides intuitive visit this page decorators to restrict route access to authenticated users or specific administrative roles.
from flask import Blueprint, render_template
from flask_security import auth_required, roles_required, current_user
main_bp = Blueprint('main', __name__)
@main_bp.route('/dashboard')
@auth_required() # Requires user to be logged in
def dashboard():
return render_template('dashboard.html', user=current_user)
@main_bp.route('/admin-panel')
@roles_required('admin') # Requires user to have the 'admin' role
def admin_panel():
return render_template('admin.html')
2. Multi-Factor Authentication (MFA) and WebAuthn
Modern applications demand robust defense beyond simple passwords. Flask-Security-Too includes first-class support for Multi-Factor Authentication. Users can configure time-based one-time passwords (TOTP) via authenticator apps like Google Authenticator or Authy, or register hardware keys using WebAuthn/Passkeys.
Enabling MFA is handled through configuration flags:
app.config['SECURITY_TWO_FACTOR_ENABLED'] = True
app.config['SECURITY_TWO_FACTOR_ENTIFIERS'] = ['authenticator']
Quick Reference: Key Configuration Options
| Configuration Key | Default Value | Description |
|---|---|---|
SECURITY_REGISTERABLE | False | Enables user registration endpoints (/register). |
SECURITY_CONFIRMABLE | False | Requires users to confirm their email address before logging in. |
SECURITY_RECOVERABLE | False | Enables password recovery and reset workflows (/reset). |
SECURITY_TRACKABLE | False | Tracks login count, last login IP address, and timestamps. |
SECURITY_PASSWORD_HASH | 'pbkdf2_sha512' | Specifies the secure hashing algorithm used for passwords. |
Production Security Best Practices
When deploying a Flask application secured with Flask-Security-Too to production, engineering teams must maintain strict adherence to security hardening standards:
- Secure Environment Variables: Never hardcode
SECRET_KEYorSECURITY_PASSWORD_SALTinto source code. Always load them securely from environment variables using robust secret management systems. - Enforce HTTPS and Secure Cookies: Configure session cookies to require HTTPS by setting
SESSION_COOKIE_SECURE = True,SESSION_COOKIE_HTTPONLY = True, andSESSION_COOKIE_SAMESITE = 'Lax'or'Strict'. - Configure Password Complexity Rules: Enable strict password validation policies in Flask-Security-Too to require minimum lengths, mixed casing, numbers, and special symbols, protecting users against credential stuffing attacks.
Summary
Flask-Security-Too bridges the gap between Flask’s unopinionated micro-framework philosophy and the rigorous security requirements of modern web development. By bundling authentication, role-based access control, Source password management, and multi-factor authentication into a single robust extension, Flask-Security-Too empowers development teams to build secure, scalable applications with confidence.