flask-security-too is the actively maintained authentication and authorization extension for Flask that grew out of the original, long-dormant Flask-Security project, bundling session-based login, password hashing, role-based access, and account flows like registration, confirmation, and recovery into one package. For a while the naming was confusing, so here is the current state: the "Too" fork is now part of the Pallets Community Ecosystem, and as of mid-2024 the same release is published to both the Flask-Security and Flask-Security-Too names on PyPI, with the version line continuing past 5.8. If you are starting fresh, install whichever name you like; you get the same maintained code.
Because it wires together several security-sensitive features at once, the value is real but so is the responsibility to configure it correctly. The defaults are sane, yet a few settings decide whether your login flow is genuinely safe.
What the extension gives you
Out of the box, flask-security-too covers the parts of auth most teams would otherwise assemble from a dozen smaller libraries: a UserDatastore abstraction over SQLAlchemy or MongoDB, password hashing, session management, "remember me" tokens, role and permission decorators, and optional flows for email confirmation, password reset, account lockout, and multi-factor authentication.
A minimal setup looks like this:
from flask import Flask
from flask_security import Security, SQLAlchemyUserDatastore
app = Flask(__name__)
app.config["SECRET_KEY"] = "load-from-environment-not-here"
app.config["SECURITY_PASSWORD_SALT"] = "also-from-environment"
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
The SECRET_KEY signs the session cookie and SECURITY_PASSWORD_SALT is used in token generation. Both must be high-entropy values loaded from the environment or a secrets manager, never committed. A leaked SECRET_KEY lets an attacker forge sessions.
Pin the version and track advisories
Because flask-security-too pulls in a stack of dependencies, Flask-Login, Flask-WTF, passlib, and an email or token library among them, it sits at the center of a small dependency tree that is entirely in your authentication path. A vulnerability in any of them is a vulnerability in your login.
Pin the version explicitly and upgrade deliberately after reading the changelog:
Flask-Security-Too==5.8.1
Watch the GitHub Security advisories for the pallets-eco/flask-security repository and subscribe to release notes. Because this library and its dependencies all live on the critical auth path, run a dependency scan on every build; an SCA tool such as Safeguard can flag a vulnerable passlib or Flask-WTF pulled in transitively before it reaches production. Our software composition analysis coverage explains how those transitive auth dependencies surface.
Choose a strong password hash
flask-security-too delegates password hashing to passlib and lets you pick the scheme through SECURITY_PASSWORD_HASH. The right choice is a modern, deliberately slow algorithm. bcrypt is a safe default and argon2 is stronger if you can add the argon2-cffi dependency.
app.config["SECURITY_PASSWORD_HASH"] = "argon2"
Avoid any fast general-purpose hash. If you inherit an app configured with an outdated scheme, passlib supports transparent rehashing on the next successful login, so you can migrate users to a stronger algorithm without a forced reset.
Harden the session and account flows
The extension leans on Flask's session cookie, so the cookie hardening rules apply directly. Set the flags that keep the session token off JavaScript and off plaintext connections:
app.config["SESSION_COOKIE_HTTPONLY"] = True
app.config["SESSION_COOKIE_SECURE"] = True
app.config["SESSION_COOKIE_SAMESITE"] = "Lax"
Serve the whole app over HTTPS so SESSION_COOKIE_SECURE is meaningful. For the account flows, enable email confirmation with SECURITY_CONFIRMABLE so unverified addresses cannot log in, and turn on tracking and lockout features to slow credential-stuffing attempts. Keep the CSRF protection that Flask-WTF provides enabled for the login and account forms; disabling it to "simplify" an API is a common self-inflicted wound. The broader reasoning behind these settings is in our guide to secure session management.
Do not skip the token settings
The password-reset and confirmation tokens are time-limited by design. Keep the expiry windows short, SECURITY_RESET_PASSWORD_WITHIN and SECURITY_CONFIRM_EMAIL_WITHIN accept human-readable durations like 24 hours, so a leaked reset link does not stay live for a week. And make sure the SECURITY_PASSWORD_SALT used to generate these tokens is distinct from your SECRET_KEY and equally protected.
FAQ
Is flask-security-too the same as Flask-Security?
Effectively yes now. flask-security-too began as a maintained fork of the abandoned Flask-Security, and it is now published under both names from the Pallets Community Ecosystem, with the same release going to each. New projects can install either name and get the maintained code.
Which password hash should I configure?
Use bcrypt as a solid default or argon2 for a stronger, memory-hard option, which requires the argon2-cffi dependency. Avoid fast hashes like plain SHA-256 for passwords.
Does flask-security-too handle CSRF protection?
Yes, through its Flask-WTF integration, and it is enabled for the built-in forms by default. Keep it on for login and account actions rather than disabling it for convenience.
How do I keep the extension secure over time?
Pin the version, read the changelog before upgrading, watch the project's GitHub security advisories, and scan your dependency tree on every build since the whole tree sits on your authentication path.