Flask-Security
raw JSON → 5.8.0 verified Fri May 01 auth: no python
Flask-Security is a library that adds common security features to Flask applications, including authentication, role management, password hashing, email confirmation, and session management. Current version is 5.8.0, requiring Python >=3.10. Released under pallets-eco as the successor to Flask-Security-Too.
pip install flask-security Common errors
error ImportError: cannot import name 'FlaskSecurity' from 'flask_security' ↓
cause Flask-Security 5.x renamed the class from FlaskSecurity to Security.
fix
Change import to 'from flask_security import Security'.
error TypeError: 'NoneType' object is not subscriptable when accessing user.roles ↓
cause Missing backref or roles_users table not defined correctly.
fix
Ensure the secondary table for roles (e.g., 'roles_users') is defined as a SQLAlchemy model with proper foreign keys.
error AttributeError: 'NoneType' object has no attribute 'get' when using login_required ↓
cause Flask-Security's login_required decorator expects the current_user proxy to be available (via Flask-Login).
fix
Make sure Flask-Login is installed and 'flask_security' is initialized after the app config is set.
Warnings
breaking Flask-Security-Too has been merged into Flask-Security 5.x. The import paths changed: use 'flask_security' (not 'flask_security_too'). The class name for Security init changed from 'FlaskSecurity' to 'Security'. ↓
fix Update imports: 'from flask_security import Security' instead of 'from flask_security_too import FlaskSecurity'.
deprecated The 'login_required' decorator from 'flask_security.decorators' is deprecated; import from 'flask_security' directly. ↓
fix Use 'from flask_security import login_required'.
gotcha When using custom forms, you must register custom templates in 'SECURITY_REGISTERABLE' and related config options, else forms may not render correctly. ↓
fix Set 'SECURITY_REGISTERABLE = True' and configure 'SECURITY_LOGIN_USER_TEMPLATE' etc.
Imports
- Security wrong
from flask_security import FlaskSecuritycorrectfrom flask_security import Security - SQLAlchemyUserDatastore
from flask_security import SQLAlchemyUserDatastore - UserMixin
from flask_security import UserMixin - RoleMixin
from flask_security import RoleMixin - login_required wrong
from flask_security.decorators import login_requiredcorrectfrom flask_security import login_required
Quickstart
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin, login_required
app = Flask(__name__)
app.config['SECRET_KEY'] = 'super-secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SECURITY_PASSWORD_SALT'] = 'salty-salt'
db = SQLAlchemy(app)
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'))
class RolesUsers(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
role_id = db.Column(db.Integer, db.ForeignKey('role.id'))
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
@app.route('/')
@login_required
def home():
return 'Hello, user!'
with app.app_context():
db.create_all()
if not User.query.filter_by(email='test@example.com').first():
user_datastore.create_user(email='test@example.com', password='password')
db.session.commit()
if __name__ == '__main__':
app.run()