{"id":7242,"library":"flask-security-too","title":"Flask-Security-Too","description":"Flask-Security-Too quickly adds common security features like user registration, login, roles, and password management to your Flask application. Currently at version 5.8.0, it's the actively maintained successor to the original Flask-Security, frequently releasing updates with fixes and improvements. Despite the 'too' suffix in its PyPI name, it is now the official Flask-Security project under Pallets-Eco.","status":"active","version":"5.8.0","language":"en","source_language":"en","source_url":"https://github.com/pallets-eco/flask-security","tags":["flask","security","authentication","authorization","users","registration","login"],"install":[{"cmd":"pip install flask-security-too Flask-SQLAlchemy","lang":"bash","label":"Install with SQLAlchemy support"},{"cmd":"pip install flask-security-too[email]","lang":"bash","label":"Install with email support (requires Flask-Mail)"}],"dependencies":[{"reason":"Core Flask integration.","package":"Flask"},{"reason":"User session management (internal dependency).","package":"Flask-Login"},{"reason":"Password hashing and management.","package":"Passlib"},{"reason":"Required for using the SQLAlchemy user datastore.","package":"Flask-SQLAlchemy","optional":true},{"reason":"Required for email features like password reset and confirmation.","package":"Flask-Mail","optional":true}],"imports":[{"note":"Despite the PyPI package name `flask-security-too`, the Python module name is `flask_security`.","wrong":"from flask_security_too import Security","symbol":"Security","correct":"from flask_security import Security"},{"symbol":"SQLAlchemySessionUserDatastore","correct":"from flask_security import SQLAlchemySessionUserDatastore"},{"symbol":"UserMixin","correct":"from flask_security import UserMixin"},{"symbol":"RoleMixin","correct":"from flask_security import RoleMixin"}],"quickstart":{"code":"import os\nfrom flask import Flask\nfrom flask_sqlalchemy import SQLAlchemy\nfrom flask_security import Security, SQLAlchemySessionUserDatastore, UserMixin, RoleMixin\n\n# Configure Flask app\napp = Flask(__name__)\napp.config['DEBUG'] = True\napp.config['SECRET_KEY'] = os.environ.get('FLASK_SECRET_KEY', 'super-secret-dev-key')\napp.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'\napp.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\napp.config['SECURITY_PASSWORD_SALT'] = os.environ.get('SECURITY_PASSWORD_SALT', 'some-random-salt')\n\n# Initialize SQLAlchemy\ndb = SQLAlchemy(app)\n\n# Define User and Role models\nroles_users = db.Table(\n    'roles_users',\n    db.Column('user_id', db.Integer, db.ForeignKey('user.id')),\n    db.Column('role_id', db.Integer, db.ForeignKey('role.id'))\n)\n\nclass Role(db.Model, RoleMixin):\n    id = db.Column(db.Integer, primary_key=True)\n    name = db.Column(db.String(80), unique=True)\n    description = db.Column(db.String(255))\n\nclass User(db.Model, UserMixin):\n    id = db.Column(db.Integer, primary_key=True)\n    email = db.Column(db.String(255), unique=True)\n    password = db.Column(db.String(255))\n    active = db.Column(db.Boolean())\n    fs_uniquifier = db.Column(db.String(64), unique=True, nullable=False)\n    roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic'))\n\n# Setup Flask-Security\nuser_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role)\nsecurity = Security(app, user_datastore)\n\n@app.before_first_request\ndef create_user():\n    db.create_all()\n    if not user_datastore.find_user(email='test@example.com'):\n        user_datastore.create_user(email='test@example.com', password='password')\n    db.session.commit()\n\n@app.route('/')\ndef home():\n    return 'Hello, Flask-Security-Too! Go to /login or /register.'\n\nif __name__ == '__main__':\n    app.run()\n","lang":"python","description":"This quickstart sets up a basic Flask application with Flask-SQLAlchemy and Flask-Security-Too, enabling user registration and login functionality. It defines simple User and Role models and initializes the `Security` extension with a `SQLAlchemySessionUserDatastore`. Remember to set `FLASK_SECRET_KEY` and `SECURITY_PASSWORD_SALT` environment variables in production."},"warnings":[{"fix":"Always use `from flask_security import ...` for imports.","message":"The PyPI package name is `flask-security-too`, but the Python module to import from is `flask_security`. Attempting to import from `flask_security_too` will result in a `ModuleNotFoundError`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Consult the official Flask-Security-Too documentation regarding `SECURITY_PASSWORD_SCHEMES` and `Passlib` configuration for your specific upgrade path.","message":"Upgrading from very old `Flask-Security` versions (pre-5.x) may require reviewing your password hashing configuration due to `Passlib` integration changes. Specifically, `SECURITY_PASSWORD_SCHEMES` might need to be adjusted.","severity":"breaking","affected_versions":"< 5.0.0"},{"fix":"Initialize your user datastore with `SQLAlchemySessionUserDatastore(db.session, User, Role)`.","message":"When using Flask-SQLAlchemy version 3.x or higher, it is recommended to use `SQLAlchemySessionUserDatastore` instead of `SQLAlchemyUserDatastore`. The former uses `db.session` directly, aligning better with modern Flask-SQLAlchemy practices.","severity":"gotcha","affected_versions":">= 5.0.0"},{"fix":"Generate strong, unique keys for both `SECRET_KEY` and `SECURITY_PASSWORD_SALT` and manage them securely (e.g., via environment variables).","message":"Ensure `app.config['SECRET_KEY']` and `app.config['SECURITY_PASSWORD_SALT']` are set to long, random, and distinct strings, especially in production environments. Using simple or default values compromises security.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure `flask-security-too` is installed (`pip install flask-security-too`) and use `from flask_security import ...` for all imports.","cause":"You likely installed the package `flask-security-too` but are trying to import from `flask_security_too`, or `flask-security-too` was not installed correctly.","error":"ModuleNotFoundError: No module named 'flask_security'"},{"fix":"Verify that `security = Security(app, user_datastore)` is called correctly after your Flask app and user datastore are initialized. Ensure your `SECURITY_REGISTERABLE`, `SECURITY_CONFIRMABLE` settings are consistent with the features you expect.","cause":"This usually means that the Flask-Security blueprint (which contains the 'security.login' endpoint) was not properly registered with your Flask application, or the `Security` object was not correctly initialized.","error":"werkzeug.routing.BuildError: Could not build url for endpoint 'security.login'. Did you mean 'static' instead?"},{"fix":"Check `app.config['SECURITY_PASSWORD_SCHEMES']` for correct scheme names (e.g., 'pbkdf2_sha512', 'bcrypt'). Ensure `passlib` is installed and up to date.","cause":"This error comes from Passlib, indicating that the password hashing scheme specified in `SECURITY_PASSWORD_SCHEMES` is either misspelled, not installed, or not supported by your Passlib version.","error":"Password scheme '<scheme_name>' is not supported."},{"fix":"Once `security = Security(app, user_datastore)` is called, `security` is an object. Access its functionality via `security.login_manager` or similar attributes, or use decorators like `@security.login_required`.","cause":"You are trying to call the `Security` object as if it were a function (e.g., `security()`) after it has been initialized, instead of accessing its methods or attributes.","error":"TypeError: 'Security' object is not callable"}]}