PackageTrack

PyPI

flask-security-too

5.8.2pallets-eco/flask-security

Quickly add security features to your Flask application.

Release timeline

59 releases since 2019
20192026

One column per quarter.

Releases

  1. 5.8.212 Aug 2026
    Release notes

    Released August 11, 2026

    Fixes

      1. Fix for GHSA-f66q-9rf6-8795 - WebAuthn reauthentication freshness bypass. (tonghuaroot)

    • (1263) SECURITY_CACHE_CONTROL directives were added to every application response instead of just responses from Flask-Security endpoints as documented. (Ceirced)

      1. Newly introduced .UserMixin.is_locked logic is inverted.

      1. Fix login form remember me checkbox.

    Backwards Compatibility Concerns

    • The fix for the inverted is_locked logic will require any application using it to invert their logic.

    Open source →
    Additional notes

    Release 5.8.2 Latest

    Latest

    Compare

    Choose a tag to compare

    Open source →
  2. 5.8.121 May 2026
    Release notes

    Released May 21, 2026

    Fixes

      1. Fix for GHSA-w2j7-f3c6-g8cw - Possible open-redirect with ALLOW_SUBDOMAIN option.

      1. Fix for GHSA-97r5-pg8x-p63p - possible oauth bypass in /verify

    Open source →
    Additional notes

    Release 5.8.1

    Compare

    Choose a tag to compare

    Open source →
  3. 5.8.015 Apr 2026
    Release notes

    Released April 15, 2026

    Features & Improvements

    • (1170) Add API .UserMixin.check_tf_required to allow applications to control which users require two-factor authentication.

      1. Add Cache-Control headers.

      1. Add support for using Social Login (OAuth) for verification.

    • (1188) Add tracking of failed authentication attempts via .UserMixin.track_failed_authn and signal user_failed_authn

      1. Add API for application to decide if a particular user account is locked.

    Fixes

      1. Fix verify_password for bcrypt 5.0 (mephi42)

      1. Fix username_recovery w.r.t. inactive and non-confirmed users

      1. Return additional fields for JSON responses with QR codes

    Docs and Chores

      1. Update de_DE translations (swaeberle)

      1. Update ca_ES translations (arielvb)

      1. Update es_ES translations (arielvb)

      1. Update arabic translations (samialfattani)

      1. Update it_IT translations (gissimo)

      1. Change external facing terminology from 'Social OAuth' to 'Social Login'.

    Open source →
    Additional notes

    Release 5.8.0

    Compare

    Choose a tag to compare

    Open source →
  4. 5.7.123 Nov 2025
    Release notes

    This release contains a single fix for a regression in password automatic algorithm upgrade. See #1147

    Open source →
    Additional notes

    Released November 23, 2025

    Fixes

      1. Regression when updating hash algorithm from bcrypt (willcroft)

    Open source →
    Additional notes

    Release 5.7.1

    Compare

    Choose a tag to compare

    Open source →
  5. 5.7.014 Nov 2025
    Release notes

    Released November 14, 2025

    This release contains a set of small backward incompatible changes. Please read these notes carefully.

    Features & Improvements

      1. Add Arabic translations (samialfattani)

      1. Enable forgot-password workflow for authenticated users.

    Fixes

      1. Fix broken link in docs and improve docstrings/typing for util classes.

      1. Add nonce to script tags if configured to support nonce-based Content-Security-Policy (ahanak).

      1. Remove unnecessary (optional) dependency on sqlalchemy_utils.

      1. Fix localization of tf_select choices.

      1. Support bcrypt 5.0 - See below for important compatibility concerns.

      This also replaces passlib with libpass for all versions.

    Docs and Chores

      1. Update ES and IT translations (gissimo)

      1. Drop support for Python 3.9. This removes the dependency on importlib_resources,

      updates pypy to 3.10, and uses 3.12 as base python for tests/tox.

      1. Flip SECURITY_USE_REGISTER_V2 default to True.

      1. Flip default mail package back to Flask-Mail (from Flask-Mailman).

      1. Change external facing terminology from 'WebAuthn Credential' to 'passkey'.

      1. Setting of xx_util_cls from kwargs which was deprecated in 5.6.1 has been removed.

      The BACKWARDS_COMPAT_UNAUTHN option (code) which has been deprecated since 5.4 has been removed.

    Backwards Compatibility Concerns

    • Flask-Security now depends on libpass (https://pypi.org/project/libpass/) for all versions. Be sure to UNINSTALL passlib, ensure the passlib directory is empty and then install libpass - we have seen reports when both are installed - it doesn't work!

      In bcrypt 5.0 they started throwing a ValueError for passwords/secrets longer than 72 bytes. It is important to know that by default Flask-Security performs a double hash - taking the secret, using HMAC(SHA512) then b64encodng the result. This means that ANY password will be longer than 72 bytes (86 to be exact). In the past bcrypt would silently truncate the input - now we have to do that explicitly. OWASP says truncation concerns are negligible: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#input-limits-of-bcrypt

    • The default RegisterForm is now the new RegisterFormV2 - Please read register_form_migration. Flask-Security will emit a DeprecationWarning if the SECURITY_USE_REGISTER_V2 is set to False.

    • In 5.0 we changed the default mailer package to Flask-Mailman since Flask-Mail was no longer supported. Flask-Mail is again supported and is part of Pallets-Eco. Both packages are still supported based on which one an application initializes. The only backwards compatibility concern is that if you use the setup extras 'common', it will install Flask-Mail rather than Flask-Mailman.

    • In the optional dependencies 'fsqla' we removed sqlalchemy_utils - while many applications might want these useful add-ons - they aren't required for standard SQLAlchemy use.

    Open source →
    Additional notes

    Release 5.7.0

    Compare

    Choose a tag to compare

    Open source →
  6. 5.6.24 May 2025
    Release notes
    • Fix setuptool issues with Python 3.12/3.13 and passlib
    • Improve welcome_existing email template (include confirmation and reset links)
    Open source →
    Additional notes

    Released May 4, 2025

    Fixes

    • (1032 and 1096) Use libpass for python >= 3.12

      1. Fix FR translation test for Change Password (nickcuenca)

      1. Properly document context variables available in email templates.

      1. Add confirmation link/token and reset link/token to welcome_existing email template.

    Notes

    Since Python 3.12 no longer contains setuptools - the old passlib failed to import. Rather than require setuptools, for Python >=3.12 we now depend on the fork libpass (https://pypi.org/project/libpass/) This is a very new package and rather than possibly cause backwards compat issues for projects not using Python >=3.12 - Flask-Security maintains the dependency on passlib for Python <3.12.

    Note: you can still use passlib for 3.12 and 3.13 - you have to manually add setuptools.

    Open source →
    Additional notes

    Release 5.6.2 - Flask-Security-Too

    Compare

    Choose a tag to compare

    Open source →
  7. 5.6.118 Mar 2025
    Release notes

    Released March 18, 2025

    Fixes

      1. Fix runtime modification of a config string (TWO_FACTOR_METHODS)

      1. Fix CLI user_create when model doesn't contain username

      1. xxx_util_cls instances should be public and documented.

    Backwards Compatibility Concerns

    As part of 1076 the following cleanup was done:

    • The xxx_util_cls arguments are now stored in 'private' instance variables - they are never used after Flask-Security initialization and have never been documented.

    • The xxx_util_cls options should only be set as part of Flask-Security construction. Setting them via init_app(kwargs) or app.config["SECURITY_XX"] has been deprecated.

    Open source →
    Additional notes

    Release 5.6.1

    Compare

    Choose a tag to compare

    Open source →
  8. 5.6.012 Feb 2025
    Release notes

    Released February 12, 2025

    Features & Improvements

      1. Add support for 'secret_key' rotation (jamesejr)

      1. Add support for username recovery in simple login flows (jamesejr)

      1. Add support for changing username

      1. Add support for Python 3.13

      1. Unify Register forms (and split out re-type password option) Please read register_form_migration.

    Fixes

      1. Fix duplicate HTML ids in templates.

      1. Fix more duplicate HTML ids in templates.

      1. Ensure templates pass W3C validation (see below)

    Docs and Chores

      1. Remove deprecated TWO_FACTOR configuration variables

      1. Update ES and IT translations (gissimo)

    • (1071) Improve templates - two-factor is hyphenated, re-authenticate is not. Also try to embed links into xlatable strings.

    Notes

    Python 3.13 removed crypt, which passlib attempts to import and use as part of its safe_crypt() method (fallback is to return None). However - that method only appears to be called in a few crypt handlers and for bcrypt - only for the built-in bcrypt - not if the bcrypt package is installed. passlib is not maintained - a new fork (10/1/2024) (https://pypi.org/project/libpass/) seems promising and has been tested with python 3.13 and Flask-Security. If that fork matures we will change the dependencies appropriately.

    The register forms have been combined - or more accurately - there is a new RegisterFormV2 that subsumes the features of both the old RegisterForm and ConfirmRegisterForm. Please read register_form_migration.

    The SECURITY_TWO_FACTOR_{SECRET, URI_SERVICE_NAME, SMS_SERVICE, SMS_SERVICE_CONFIG} have been removed (they have been deprecated for a while). Use the equivalent SECURITY_TOTP_SECRETS, SECURITY_TOTP_ISSUER, SECURITY_SMS_SERVICE and SECURITY_SMS_SERVICE_CONFIG.

    Backwards Compatibility Concerns

    The fixes to all the templates to pass W3C validation could introduce some incompatibilities:

    • All templates now have a default <title> - before, the <title> element was empty.

    • The HTML id of the rescue form submit button was changed to 'rescue'

    • The HTML id of the webauthn delete form name field was changed to 'delete-name'

    • Some template headings were changed to improve consistency

    • The csrf_token HTML id was changed on us_setup.html, wan_register.html, two_factor_setup.html two_factor_verify_code.html, us_verify.html, verify.html for the second form on the page.

    • On us_setup.html and two_factor_setup.html the submit code button HTML id was changed.

    Open source →
    Additional notes

    Release 5.6.0 - Flask-Security

    Compare

    Choose a tag to compare

    Open source →
  9. 5.5.24 Aug 2024
    Release notes

    Released August 5, 2024

    More attempts to upload to pypi both flask-security and flask-security-too. No code changes - however the build manifest changed so the source distribution contents might be slightly different.

    Docs and Chores

      1. Separate publish workflows for each pypi package

    Open source →
  10. 5.5.024 Jul 2024
    Release notes

    Released July 24, 2024

    Features & Improvements

      1. Add support for changing registered user's email (SECURITY_CHANGE_EMAIL).

      1. Change default password hash to argon2 (was bcrypt). See below for details.

      1. Add freshness capability to auth tokens (enables /us-setup to function w/ just auth tokens).

      1. Add support to /tf-setup to not require sessions (use a state token).

    • (994) Add support for Flask-SQLAlchemy-Lite - including new all-inclusive models that conform to sqlalchemy latest best-practice (type-annotated).

      1. Convert other sqlalchemy-based datastores from legacy 'model.query' to best-practice 'select'

      1. Allow applications more flexibility defining allowable redirects.

    Fixes

    • (972) Set SECURITY_CSRF_COOKIE at beginning (GET /login) of authentication ritual - just as we return the CSRF token. (thanks @e-goto)

      1. login and unified sign in should handle GET for authenticated user consistently.

      1. Don't show sms options if not defined in US_ENABLED_METHODS. (fredipevcin)

      1. Change SECURITY_DEPRECATED_HASHING_SCHEMES to ["auto"].

    Docs and Chores

      1. Update Russian translations (ademaro)

      1. Update ES and IT translations (gissimo)

    • (981 and 977) Improve docs

      1. The long deprecated get_token_status is no longer exported

      1. Drop Python 3.8 support.

      1. Try a different approach to typing User and Role models.

    Backwards Compatibility Concerns

    • Notes around the change to argon2 as the default password hash:
      • applications should add the argon2_cffi package to their requirements (it is included in the flask_security[common] extras).

      • leave bcrypt installed so that old passwords still work.

      • the default configuration will re-hash passwords with argon2 upon first use.

    • Changes to /tf-setup

      The old path - using state set in the session still works as before. The new path is just for the case an authenticated user wants to change their 2FA setup.

    • Changes to sqlalchemy-based datastores

      Flask-Security no longer uses the legacy model.query - all DB access is done via select(xx).where(xx). As a result the find_user() method now only takes a SINGLE column:value from its kwargs - in prior releases all kwargs were passed into the query.filter.

    Open source →
  11. 5.4.323 Mar 2024
    Release notes

    Released March 23, 2024

    Fixes

      1. Regression - some templates no longer getting correct config (thanks pete7863).

      1. CSRF not properly ignored for application forms using SECURITY_CSRF_PROTECT_MECHANISMS.

      1. Improve jp translations (e-goto)

      1. Regression - datetime_factory should still be an attribute (thanks TimotheeJeannin)

      1. SECURITY_RETURN_GENERIC_RESPONSES hid email validation/syntax errors.

    Open source →
  12. 5.4.29 Mar 2024
    Release notes

    Released March 8, 2024

    Fixes

      1. OpenAPI spec missing.

      1. Doc fixes (e-goto)

      1. Update ES/IT translations (gissimo)

    Open source →
  13. 5.4.127 Feb 2024

    Nothing published for this version

  14. 5.4.026 Feb 2024withdrawn: mixup - 5.4.1 out really soon
    Release notes

    Released February 26, 2024

    Among other changes, this continues the process of dis-entangling Flask-Security from Flask-Login and may require some application changes due to backwards incompatible changes.

    Features & Improvements

      1. Work with Flask[async]. view decorators and signals support async handlers.

      1. CI support for python 3.12

      1. Work with py_webauthn 2.0 (and only 2.0+)

      1. Improve (and simplify) Two-Factor setup. See below for backwards compatability issues and new functionality.

      1. Improve oauth debugging support. Handle next propagation in a more general way.

      1. Make AnonymousUser (Flask-Login) optional and deprecated.

    • (906) Remove undocumented and untested looking in session for possible 'next' redirect location.

      1. No longer rely on Flask-Login.unauthorized callback. See below for implications.

      1. Changes to default unauthorized handler - remove use of referrer header (see below) and document precise behavior.

    • (927) The authentication_token format has changed - adding per-token expiry time and future session ID. Old tokens are still accepted.

    Docs and Chores

      1. Improve method translations for unified signin and two factor. Remove support for Flask-Babelex.

    • (911) Chore - stop setting all config as attributes. init_app(**kwargs) can only set forms, flags, and utility classes (see below for compatibility concerns).

      1. Update Spanish and Italian translations. (gissimo)

      1. Improve translations for two-factor method selection. (gissimo)

      1. Improve German translations. (sr-verde)

      1. Remove deprecation of AUTO_LOGIN_AFTER_CONFIRM - it has a reasonable use case.

    • (931) Update message extraction - note that the CONFIRM_REGISTRATION message was changed to improve readability.

    Fixes

      1. us-signin magic link should use fs_uniquifier (not email).

      1. Improve open-redirect vulnerability mitigation. (see below)

      1. user_datastore.create_user has side effects on mutable inputs. (NoRePercussions)

      1. The long deprecated _unauthorized_callback/handler has been removed.

      1. Oauth re-used POST_LOGIN_VIEW which caused confusion. See below for the new configuration and implications.

    • (908) Improve CSRF documentation and testing. Fix bug where a CSRF failure could return an HTML page even if the request was JSON.

      1. Register with JSON and authentication token failed CSRF. (lilz-egoto)

      1. Fix 2 issues with CSRF configuration.

    • (914) It was possible that if SECURITY_EMAIL_VALIDATOR_ARGS were set that deliverability would be checked even for login.

    Backwards Compatibility Concerns

    • Passing in an AnonymousUser class as part of Security initialization has been removed.

    • The never-public method _get_unauthorized_response has been removed.

    • Social-Oauth - a new configuration variable SECURITY_POST_OAUTH_LOGIN_VIEW was introduced and it replaces SECURITY_POST_LOGIN_VIEW in the oauthresponse logic when SECURITY_REDIRECT_BEHAVIOR == "spa".

    • Two-Factor setup. Prior to this release when setting up "SMS" the /tf-setup endpoint could be POSTed to w/o a phone number, and then another POST could be made to set the phone number. This has always been confusing and added complexity to the code. Now, if "SMS" is selected, the phone number must be supplied (which has always been supported). Other changes:

      • The default two-factor-setup.html template now has a more generic "Enter code to complete setup" message.

      • Make sure the "disable" option first.

      • Adding any currently configured two-factor method on setup failure.

      • The two_factor_verify template won't show the rescue form if it isn't set.

      • A GET on /tf-validate now returns the two-factor-validate-form always - before if the client was validating a new method, it would return the two-factor-setup-form

      • After successfully disabling two-factor the client is redirected to SECURITY_TWO_FACTOR_POST_SETUP_VIEW rather than SECURITY_POST_LOGIN_VIEW.

    • Bring unauthenticated handling completely into Flask-Security:

      Prior to this release, Flask-Security's .Security.unauthn_handler - called when a request wasn't properly authenticated - handled JSON requests then delegated form responses to Flask-Login's unauthenticated_callback. That logic has been moved into Flask-Security and Flask-Login is configured to call back into Flask-Security's handler. While the logic is very similar the following differences might be observed:

      • Flask-Login's FORCE_HOST_FOR_REDIRECTS configuration isn't honored

      • Flask-Login's USE_SESSION_FOR_NEXT configuration isn't honored

      • The flashed message is SECURITY_MSG_UNAUTHENTICATED rather than SECURITY_MSG_LOGIN. Furthermore, SECURITY_MSG_UNAUTHENTICATED was reworded to read better.

      • Flask-Login uses urlencode to encode the next query param - which quotes the '/' character. Werkzeug (which Flask-Security uses to build the URL) uses quote which considers '/' a safe character and isn't encoded.

      • The signal sent on an unauthenticated request has changed to user_unauthenticated. Flask-Login used to send a user_unauthorized signal.

    • Flask-Security no longer configures anything related to Flask-Login's fresh_login logic. This shouldn't be used - instead use Flask-Security's flask_security.auth_required decorator.

    • Support for Flask-Babelex has been removed. Please convert to Flask-Babel.

    • JSON error response has changed due to issue with WTForms form-level errors. When WTForms introduced form-level errors they added it to the form.errors response using None as a key. When serializing it, it would turn into "null". However, if there is more than one error the default settings for JSON serialization in Flask attempt to sort the keys - which fails with the None key. An issue has been filed with WTForms - and maybe it will be changed. Flask-Security now changes any None key to "".

    • The default unauthorized handler behavior has changed slightly and is now documented. The default (SECURITY_UNAUTHORIZED_VIEW == None) has not changed (a default HTTP 403 response). The precise behavior when SECURITY_UNAUTHORIZED_VIEW is set was never documented. The important change is that Flask-Security no longer ever looks at the request.referrer header and will never redirect to it. If an application needs that, it can provide a callable that can return that or any other header.

    • Configuration variables (and other things) are no longer added as attributes on the Security instance. For example security.username_enable no longer exists - this could be an issue in code or templates. For templates, Flask places config in the Jinja context - so rather than using an attribute, use config["SECURITY_USERNAME_ENABLE"] for the example above.

    • Open Redirect mitigation. Release 4.1.0 had a fix for 486 involving a potential open redirect. This was very low priority since the default configuration of Werkzeug (always convert the Location header to absolute URL) rendered the vulnerability un-exploitable. The solution at that time was to add an optional regex looking for these bizarre URLs that from a HTTP spec perspective are relative, but various browsers would interpret as absolute. In Werkzeug release 2.1 the default was changed so that the Location header was allowed to be a relative URL. This made the open redirect vulnerability much more likely to be exploitable. More recently, additional bizarre URLs were found, as documented in 893. More work was done and a patch release 5.3.3 was published. This fix utilized changing the Werkzeug default back to absolute and an updated regex. Comments and thoughts by @gmanfuncky proposed a much better solution and that is in 5.4. This implementation is independent of Werkzeug (and relative Location headers are again the default). The entire regex option has been removed. Instead, any user-supplied path used as a redirect is parsed and quoted.

    Notes

    • Historically, the current_user proxy (managed by Flask-Login) always pointed to a user object. If the user wasn't authenticated, it pointed to an AnonymousUser object. With this release, setting SECURITY_ANONYMOUS_USER_DISABLED to True will force current_user to be set to None if the requesting user isn't authenticated. It should be noted that this is in support of a proposal by the Pallets team to remove AnonymousUser from Flask-Login - as well as deprecating the is_authenticated property. The default behavior (False) should be the same as prior releases. A new function _fs_is_user_authenticated is now part of the render_template context that templates can use instead of current_user.is_authenticated.

    Open source →
  15. 5.3.330 Dec 2023
    Release notes

    Released December 29, 2023

    Fixes

    • (893) Once again work on open-redirect vulnerability - this time due to newer Werkzeug. Addresses: CVE-2023-49438

    Open source →
  16. 5.3.224 Oct 2023
    Release notes

    Released October 23, 2023

    Fixes

      1. Update Quickstart to show how to properly handle SQLAlchemy connections.

      1. Auth Token not returned from /tf-validate. (thanks lilz-egoto)

      1. Fix for latest email_validator deprecation - bump minimum to 2.0.0

      1. Deprecate passing in the anonymous_user class (sent to Flask-Login).

    Open source →
  17. 5.3.115 Oct 2023
    Release notes

    Released October 14, 2023

    Please Note:

    • If your application uses webauthn you must use pydantic < 2.0 until the issue with user_handle is resolved.

    Fixes

      1. Compatability with Flask 3.0 (wangsha)

      1. Revert change in 5.3.0 that added a Referrer-Policy header.

      1. Fix error in quickstart (codycollier)

      1. Update Armenian translations (amkrtchyan-tmp)

      1. Update German translations. (sr-verde)

      1. Fix 'next' propagation when passed as form.next (thanks cariaso)

    Open source →
  18. 5.3.026 Jul 2023
    Release notes

    Released July 27, 2023

    This is a minor version bump due to some small backwards incompatible changes to WebAuthn, recoverability (/reset), confirmation (/confirm) and the two factor validity feature.

    Fixes

      1. Webauthn Updates to handling of transport.

    • (809) Fix MongoDB support by eliminating dependency on flask-mongoengine. Improve MongoDB quickstart.

      1. Fix Quickstart for SQLAlchemy with scoped session.

      1. Login no longer, by default, checks for email deliverability.

    • (791) Token authentication is no longer accepted on endpoints which only allow 'session' as authentication-method. (N247S)

      1. /reset and /confirm and GENERIC_RESPONSES and additional form args don't mix.

      1. Reset password can be exploited and other OWASP improvements.

      1. Confirmation can be exploited and other OWASP improvements.

      1. Convert to pyproject.toml, build, remove setup.py/.cfg.

    • (823) the tf_validity feature now ONLY sets a cookie - and the token is no longer returned as part of a JSON response.

      1. Fix login/unified signin templates to properly send CSRF token. Add more tests.

      1. Improve Social Oauth example code.

    Backwards Compatibility Concerns

    • To align with the W3C WebAuthn Level2 and 3 spec - transports are now part of the registration response. This has been changed BOTH in the server code (using webauthn data structures) as well as the sample JavaScript code. If an application has their own JavaScript front end code - it might need to be changed.

    • The tf_validity feature SECURITY_TWO_FACTOR_ALWAYS_VALIDATE used to set a cookie if the request was form based, and return the token as part of a JSON response. Now, this feature is ONLY cookie based and the token is no longer returned as part of any response.

    • Reset password was changed to adhere to OWASP recommendations and reduce possible exploitation:

      • A new email (with new token) is no longer sent upon expired token. Users must restart the reset password process.

      • The user is no longer automatically logged in upon successful password reset. For backwards compatibility SECURITY_AUTO_LOGIN_AFTER_RESET can be set to True. Note that this compatibility feature is deprecated and will be removed in a future release.

      • Identity information (identity, email) is no longer sent as part of the URL redirect query params.

      • The SECURITY_MSG_PASSWORD_RESET_EXPIRED message no longer contains the user's identity/email.

      • The default for SECURITY_RESET_PASSWORD_WITHIN has been changed from 5 days to 1 days.

      • The response to GET /reset/<token> sets the HTTP header Referrer-Policy to no-referrer as suggested by OWASP. PLEASE NOTE: this was backed out in 5.3.1

    • Confirm email was changed to adhere to OWASP recommendations and reduce possible exploitation:

      • A new email (with new token) is no longer sent upon expired token. Users must restart the confirmation process.

      • Identity information (identity, email) is no longer sent as part of the URL redirect query params.

      • The SECURITY_AUTO_LOGIN_AFTER_CONFIRM configuration variable now defaults to False - meaning after a successful email confirmation, the user must still sign in using the usual mechanisms. This is to align better with OWASP best practices. Setting it to True will restore prior behavior.

      • The SECURITY_MSG_CONFIRMATION_EXPIRED message no longer contains the user's identity/email.

      • The response to GET /reset/<token> sets the HTTP header Referrer-Policy to no-referrer as suggested by OWASP. PLEASE NOTE: this was backed out in 5.3.1

    Open source →
  19. 5.2.06 May 2023
    Release notes

    Released May 6, 2023

    Note: Due to rapid deprecation and removal of APIs from the Pallets team, maintaining the testing of back versions of various packages is taking too much time and effort. In this release only current versions of the various dependent packages are being tested.

    Fixes

      1. Remove old Werkzeug compatibility check.

      1. Compatibility with Quart.

      1. Remove dependence on pkg_resources / setuptools (use importlib_resources package)

      1. Fix tests to work with latest Werkzeug/Flask. Update requirements_low to match current releases.

      1. Drop support for Python 3.7

    Known Issues

    • Flask-mongoengine hasn't released in a while and currently will not work with latest Flask and Flask-Security-Too/Flask-Security (this is due to the JSONEncoder being deprecated and removed).

    Backwards Compatibility Concerns

    • The removal of pkg_resources required changing the config variable SECURITY_I18N_DIRNAME. If your application modified or extended this configuration variable, a small change will be required.

    Open source →
  20. 5.1.213 Mar 2023
    Release notes

    Released March 12, 2023

    Fixes

      1. Hungarian translations not working.

      1. Fix documentation for send_mail. (gg)

      1. Fix for latest mongoengine and mongomock.

      1. Fix inappropriate use of &thinsp& in French translations. (maxdup)

      1. Improve documentation around subclassing forms.

    Open source →
  21. 5.1.11 Mar 2023
    Release notes

    Released March 1, 2023

    Fixes

    • (740) Fix 2 Flask apps in same thread with USERNAME_ENABLE set. There was a too aggressive config check.

      1. Update Russian translations. (ademaro)

      1. Run all templates through a linter. (ademaro)

      1. Fix json/flask backwards compatibility hack.

      1. Fix quickstarts - make sure they run using flask run

      1. Fix unified signup when two-factor not enabled. (sebdroid)

      1. Add dependency on setuptools (pkg_resources). (hroncok)

    Open source →
  22. 5.1.024 Jan 2023
    Release notes

    Released January 23, 2023

    Features

      1. Expose form instantiation. See form_instantiation.

      1. Option to encrypt recovery codes.

      1. Support for authentication via 'social' oauth.

      1. Support for Python 3.11

    Fixes

      1. Fixes for Flask-SQLAlchemy 3.0.0. (jrast)

      1. Fixes for sqlalchemy 2.0.0 (jrast)

    • (697) Webauthn and Unified signin features now properly take into account blueprint prefixes.

    • (699) Properly propagate ?next=/xx - the verify, webauthn, and unified signin endpoints, that had multiple redirects, needed fixes.

      1. Add Hungarian translations. (xQwexx)

    • (701) Two factor redirects ignored url_prefix. Added a SECURITY_TWO_FACTOR_ERROR_VIEW configuration option.

    • (704) Add configurations for static folder/URL and make sure templates reference blueprint relative static folder.

    • (709) Make (some) templates look better by using single quotes instead of double quotes.

      1. Send entire context to MailUtil::send_mail (patrickyan)

      1. Support for Flask-Babel 3.0.0

    • (692) Add configuration option SECURITY_TWO_FACTOR_POST_SETUP_VIEW which is redirected to upon successful change of a two factor method.

    • (733) The ability to pass in a LoginManager instance which was deprecated in 5.0 has been removed.

    • (732) If SECURITY_USERNAME_REQUIRED was True then users couldn't login with just an email.

      1. If SECURITY_USERNAME_ENABLE is set, bleach is a requirement.

      1. The unauthz_handler now takes a function name, not the function!

    Backwards Compatibility Concerns

    • Each form class used to be set as an attribute on the Security object. With the new form instantiation model, they no longer are.

    • After a successful update/change of a two-factor method, the user was redirected to SECURITY_POST_LOGIN_VIEW. Now it redirects to SECURITY_TWO_FACTOR_POST_SETUP_VIEW which defaults to ".two_factor_setup".

    • The .Security.unauthz_handler now takes a function name - not the function - which never made sense.

    Open source →
  23. 5.0.223 Sept 2022
    Release notes

    Released September 23, 2022

    Fixes

    • (673) Role permissions backwards compatibility bug. For SQL based datastores that use Flask-Security's models.fsqla_vx - there should be NO issues. If you declare your own models - please see the 5.0.0 releases notes for required change.

    Open source →
  24. 5.0.16 Sept 2022
    Release notes

    Released September 6, 2022

    Fixes

      1. Fix Change Password regression. (tysonholub)

    Open source →
  25. 5.0.028 Aug 2022
    Release notes

    Released August 27, 2022

    PLEASE READ CHANGE NOTES CAREFULLY - THERE ARE LIKELY REQUIRED CHANGES YOU WILL HAVE TO MAKE.

    Features

      1. Support for WebAuthn.

      1. Support Two-factor recovery codes.

      1. Provide option to prevent user enumeration (i.e. Generic Responses).

      1. Support for Python 3.10.

    • (657, 655) Support for Flask >= 2.2.

      1. Improve Templates in support of JS required by WebAuthn.

      1. Add Icelandic translations. (ofurkusi)

      1. Update German translations. (sr-verde)

    • (256) Add custom HTML attributes to improve user experience. This changed LoginForm quite a bit - please see backwards compatability concerns below. The default LoginForm and template should be the same as before.

    • (638) The JSON errors response has been unified. Please see backwards compatibility concerns below.

    • Updated all-inclusive data models (fsqla_v3). Add fields necessary for the new WebAuthn and Two-Factor recovery codes features. Changed us_phone_number to be unique (but not required). Changed password to be nullable.

    Deprecations

      1. Deprecate the old passwordless feature in favor of Unified Signin.

      1. Deprecate replacing login_manager so we can possibly vendor that in in the future.

    • (654) The previously deprecated methods RoleMixin.add_permissions and RoleMixin.remove_permissions have been removed.

    • (657) The ability to pass in a json_encoder_cls as part of initialization has been removed since Flask 2.2 has deprecated and replaced that functionality.

    • (655) Flask has deprecated @before_first_request. This was used mostly in examples/quickstart. These have been changed to use app.app_context() prior to running the app. Flask-Security itself used it in 2 places - to populate _ in jinja globals if Babel wasn't initialized and to perform various configuration sanity checks w.r.t. WTF CSRF. All Flask-Security templates have been converted to use _fsdomain rather than _ so Flask-Security no longer sets _ into jinja2 globals. The configuration checks have been moved to the end of Security::init_app() - so it is now imperative that FlaskWTF::CSRFProtect() be called PRIOR to initializing Flask-Security.

    • encrypt_password method has been removed. It has been deprecated since 2.0.2

    • get_token_status has been deprecated.

    Fixes

      1. Make the required zxcvbn complexity score configurable. (mephi42)

    • (531) Get rid of Flask-Mail. Flask-Mailman is now the default preferred email package. Flask-Mail is still supported so there should be no backwards compatability issues.

      1. A delete option has been added to us-setup (form and view).

    • (625) Improve username support - the LoginForm now has a separate field for username if SECURITY_USERNAME_ENABLE is True, and properly displays input fields only if the associated field is an identity attribute (as specified by SECURITY_USER_IDENTITY_ATTRIBUTES).

    • (627) Improve empty password handling. Prior, an unguessable password was set into the user record when a user registered without a password - now, the DB user model has been changed to allow nullable passwords. This provides a better user experience since Flask-Security now knows if a user has an empty password or not. Since registering without a password is not a mainstream feature, a new configuration variable SECURITY_PASSWORD_REQUIRED has been added (defaults to True).

    • (479) A new configuration option SECURITY_TWO_FACTOR_RESCUE_EMAIL has been added that allows disabling that feature - defaults to backwards compatible True

      1. us_phone_number needs to be validated to be unique.

    Backward Compatibility Concerns

    For unified signin:

    • The redirect after a successful us-setup used to redirect to SECURITY_US_POST_SETUP_VIEW or SECURITY_POST_LOGIN_VIEW (which would default to '/'). Now it just redirects to SECURITY_US_POST_SETUP_VIEW which defaults back to the /us-setup view.

    • The ability to authenticate using a one-time email link was automatically setup by the system for all users. "email" now behaves like the other unified sign in methods and must be explicitly set up - with the exception that if a user registers WITHOUT a password, the system will setup the one-time email link option - since otherwise the user would never be able to authenticate.

    • /us-signin/send-code didn't used to check if the user account required confirmation it just sent a code and the /us-signin endpoint did the confirmation check. Now send-code does the confirmation check and won't send a code unless the user is confirmed.

    • In us-verify the 'code_methods' item now lists just active/setup methods that generate a code not ALL possible methods that generate a code.

    • SECURITY_US_VERIFY_SEND_CODE_URL and SECURITY_US_SIGNIN_SEND_CODE_URL endpoints are now POST only.

    • Empty passwords were always permitted when SECURITY_UNIFIED_SIGNIN was enabled - now an additional configuration variable SECURITY_PASSWORD_REQUIRED must be set to False.

    • SECURITY_US_VERIFY_SEND_CODE_URL and SECURITY_US_SIGNIN_SEND_CODE_URL used to send code_sent to the template. Now they flash the SECURITY_MSG_CODE_HAS_BEEN_SENT message.

    • With the addition of being able to delete a previously setup up sign in method, the signal us_profile_changed arguments have changed. method is now methods and is a list, and a new argument delete is True if a sign in option was deleted.

    Login:

    • Since the beginning of time, the flask-security login form has accepted any input in the 'email' field, and used that to check if it corresponds to any field in SECURITY_USER_IDENTITY_ATTRIBUTES. This has always been problematic and confusing - and with the addition of HTML attributes for various form fields - having a field with multiple possible inputs is no longer a viable user experience. This is no longer supported, and the LoginForm now declares the email field to be of type EmailField which requires a valid (after normalization) email address. The most common usage of this legacy feature was to allow an email or username - Flask-Security now has core support for a username option - see SECURITY_USERNAME_ENABLE. Please see custom_login_form for an example of how to replicate the legacy behavior.

    • Some error messages have changed - USER_DOES_NOT_EXIST is now returned for any identity error including an empty value.

    Other:

    • A very old piece of code in registrable, would immediately commit to the DB when a new user was created. It is now consistent with all other views, and has the caller responsible for committing the transaction - usually by setting up a flask after_this_request action. This could affect an application that captured the registration signal and stored the user object for later use - this user object would likely be invalid after the request is finished.

    • Some fields have custom HTML attributes attached to them (e.g. autocomplete, type, etc). These are stored as part of the form in the render_kw attribute. This could cause some confusion if an app had its own templates and set different attributes.

    • The keys for "/tf-rescue" select options have changed to be more 'action' oriented:

      • lost_device -> email

      • no_mail_access -> help

    • JSON error responses. THIS IS A BREAKING CHANGE. In earlier releases, the JSON error response could have either a error key which was for rare cases where there was a single non-form related error, or an errors key which was a a dict as defined by WTForms. Now, the errors key will contain a list of (localized) messages - both non-form related as well as any form related. The key field_errors will contain the dict as specified by WTForms. Please note that starting with WTForms 3.0 form-level errors are supported and show up in the dict with the field name/key of "none". There are no changes to non-error related JSON responses.

    • Permissions THIS IS A BREAKING CHANGE. The Role Model now stores permissions as a list, and requires that the underlying DB ORM map that to a supported DB type. For SQLAlchemy, this is mapped to a comma separated string (as before). For SQLAlchemy DBs the underlying Column type (UnicodeText) didn't change so no data migration should be required. However, the ORM Column type did change and requires the following change to your model:

      from flask_security import AsaList
      from sqlalchemy.ext.mutable import MutableList
      class Role(Base, RoleMixin):
          ...
          permissions = Column(MutableList.as_mutable(AsaList()), nullable=True)
          ...

      If your application makes use of Flask-Security's models.fsqla_vX classes - no changes are required. For Mongo, a ListField can be directly used.

    • CSRF - As mentioned above, it is now required that FlaskWTF::CSRFProtect(), if used, must be called PRIOR to initializing Flask-Security.

    • json_encoder_cls - As mentioned above - Flask-Security initialization no longer accepts overriding the json_encoder class. If this is required, update to Flask >=2.2 and implement Flask's JSONProvider interface.

    For templates:

    • Pretty much every template was modified to replace <p> with <div class=xx> to make styling possible and to make more complex forms more readable.

    • Many forms had places where things weren't properly localizable - that has (hopefully) been fixed.

    • The us_setup.html template was modified to add ability to delete an existing set up method.

    DB Migration

    To use the new WebAuthn feature a new table and two new columns in the User model are required. To ease updates - Flask-Security will automatically create a fs_webauthn_user_handle upon first use for existing users. If you are using Alembic the schema migration is easy:

    op.add_column('user', sa.Column('fs_webauthn_user_handle', sa.String(length=64), nullable=True, unique=True))

    If you want to allow for empty passwords as part of registration then set SECURITY_PASSWORD_REQUIRED to False. In addition you need to change your DB schema to allow the password field to be nullable.

    Open source →
  26. 4.1.628 Feb 2023

    Nothing published for this version

  27. 4.1.528 Jul 2022
    Release notes

    Released July 28, 2022

    Fixes

      1. Fix test and other failures with newer Flask-Login/Werkzeug versions.

    Open source →
  28. 4.1.419 Apr 2022
    Release notes

    Released April 19, 2022

    Fixes

      1. Fix test failures with newer Flask versions.

    Open source →
  29. 4.1.32 Mar 2022
    Release notes

    Released March 2, 2022

    Fixes

      1. Fix bug when attempting to disable register_blueprint. (halali)

      1. Fix example documentation re: generating localized messages. (kazuhei2)

      1. Make roles joinedload compatible with SQLAlchemy 2.0. (keats)

      1. Ship py.typed as part of package.

      1. Improve documentation around use of bleach and include in common install extra.

    Open source →
  30. 4.1.222 Sept 2021
    Release notes

    Released September 22, 2021

    Fixes

      1. default_reauthn_handler doesn't honor SECURITY_URL_PREFIX

      1. Improve German translations (sr-verde)

      1. Fix two-factor sample code (djpnewton)

    Open source →
  31. 4.1.111 Sept 2021
    Release notes

    Released September 10, 2021

    Fixes

      1. Fix corner case where Security object was being reused in tests.

    • (512) If USERNAME_ENABLE is set, change LoginForm field from EmailField to StringField. Also - dynamically add fields to Login and Registration forms rather than always having them - this made the RegistrationForm much simpler.

    • (516) Improved username feature handling solved issue of always requiring bleach.

      1. Improve documentation of default username validation.

    Open source →
  32. 4.1.023 Jul 2021
    Release notes

    Released July 23, 2021

    Features

      1. Add public API and CLI command to change a user's password.

    • (140) Add type hints. Please note that many of the packages that flask-security depends on aren't typed yet - so there are likely errors in some of the types.

      1. Add first-class support for using username for signing in.

    Fixes

      1. 4.0 doesn't accept 3.4 authentication tokens. (kuba-lilz)

      1. Flask-Mail sender name can be a tuple. (hrishikeshrt)

      1. Possible open redirect vulnerability.

      1. Improve/update German translation. (sr-verde)

      1. Improve handling of Babel packages.

    • (496) Documentation improvements, distribution extras, fix single message override.

      1. Improve cookie handling and default samesite to Strict.

    Backwards Compatibility Concerns

    • (488) In 4.0.0, with the addition of Flask-Babel support, Flask-Security enforced that if it could import either Flask-Babel or Flask-BabelEx, that those modules had been initialized as proper Flask extensions. Prior to 4.0.0, just Flask-BabelEx was supported - and that didn't require any explicit initialization. Flask-Babel DOES require explicit initialization. However for some applications that don't completely control their environment (such as system pre-installed versions of python) this caused applications that didn't even want translation services to fail on startup. With this release, Flask-Security still attempts to import one or the other package - however if those modules are NOT initialized, Flask-Security will simply ignore them and no translations will occur.

    • (497) The CSRF_COOKIE and TWO_FACTOR_VALIDITY cookie had their defaults changed to set samesite=Strict. This follows the Flask-Security goal of making things more secure out-of-the-box.

    • (140) Type hinting. For the most part this of course has no runtime effects. However, this required a fairly major overhaul of how Flask-Security is initialized in order to provide valid types for the many constructor attributes. There are no known compatability concerns - however initialization used to convert all arguments into kwargs then add those as attributes and merge with application constants. That no longer happens and it is possible that some corner cases don't behave precisely as they did before.

    Open source →
  33. 4.0.12 Apr 2021
    Release notes

    Released April 2, 2021

    Features

    Fixes

      1. 4.0 doesn't accept 3.4 authentication tokens. (kuba-lilz)

      1. 2-fa error: Failed to send code - improved documentation and debuggability.

      1. 2-fa error: TypeError - fixed documentation.

    • (443) Calling create user without any arguments - fixed underlying cause of translating form errors in the CLI.

      1. Email validation confusion - added documentation.

      1. Add documentation on how to override specific error messages.

      1. Don't install global-scope tests. (mgorny)

      1. Add note about updating DB using MySQL. (jugmac00)

      1. Fix documentation - uia_phone_number should be uia_phone_mapper. (dvrg)

      1. Improve chinese translations. (zxjlm)

      1. Improve basque and spanish translations. (mmozos)

      1. Add Afrikaans translations. (lonelyvikingmichael)

    • (467) Add Blinker as explicit dependency, improve/fix celery usage docs, dont require pyqrcode unless authenticator configured, improve SMS configuration variables documentation.

    Open source →
  34. 4.0.026 Jan 2021
    Release notes

    Released January 26, 2021

    PLEASE READ CHANGE NOTES CAREFULLY - THERE ARE LIKELY REQUIRED CHANGES YOU WILL HAVE TO MAKE TO EVEN START YOUR APPLICATION WITH 4.0

    Start Here

    • Your UserModel must contain fs_uniquifier

    • Either uninstall Flask-BabelEx (if you don't need translations) or add either Flask-Babel (>=2.0) or Flask-BabelEx to your dependencies AND be sure to initialize it in your app.

    • Add Flask-Mail to your dependencies.

    • If you have unicode emails or passwords read change notes below.

    Open source →
  35. 4.0.0rc220 Jan 2021pre-release
    Release notes

    Released January 18, 2021

    Features & Cleanup

    • Removal of python 2.7 and <3.6 support

    • Removal of token caching feature (a relatively new feature that had some systemic issues)

      1. Remove dependence on Flask-Mail and refactor.

      1. Remove two-factor /tf-confirm endpoint and use generic freshness mechanism.

    • (336) Remove SECURITY_BACKWARDS_COMPAT_AUTH_TOKEN_INVALID(ATE). In addition to not making sense - the documentation has never been correct.

    • (339) Require fs_uniquifier in the UserModel and stop using/referencing the UserModel primary key.

      1. Change SECURITY_USER_IDENTITY_ATTRIBUTES configuration variable semantics.

    • Remove (all?) requirements around having an 'email' column in the UserModel. API change - JSON SPA redirects used to always include a query param 'email=xx'. While that is still sent (if and only if) the UserModel contains an 'email' columns, a new query param 'identity' is returned which returns the value of .UserMixin.calc_username().

      1. Improvements and documentation for two-factor authentication.

      1. Add support for email validation and normalization (see .MailUtil).

      1. Normalize unicode passwords (see .PasswordUtil).

    • (391) Option to redirect to /confirm if user hits an endpoint that requires confirmation. New option SECURITY_REQUIRES_CONFIRMATION_ERROR_VIEW which if set and the user hits the /login, /reset, or /us-signin endpoint, and they require confirmation the response will be a redirect. (SnaKyEyeS)

      1. Allow redirects on sub-domains. Please see SECURITY_REDIRECT_ALLOW_SUBDOMAINS. (willcroft)

    • (376) Have POST redirects default to Flask's APPLICATION_ROOT. Previously the default configuration was /. Now it first looks at Flask's APPLICATION_ROOT configuration and uses that (which also by default is /. (tysonholub)

      1. Add 2FA Validity Window so an application can configure how often the second factor has to be entered. (baurt)

      1. Add HTML5 Email input types to email fields. This has some backwards compatibility concerns outlined below. (drola)

      1. Add hy_AM translations. (rudolfamirjanyan)

      1. Add Basque and fix Spanish translations. (mmozos)

      1. Polish translations. (kamil559)

      1. Update ru_RU translations. (TitaniumHocker)

    Fixed

    • (389) Fixes for translations. First - email subjects were never being translated. Second, converted all templates to use _fsdomain(xx) rather than _(xx) so that they get translated regardless of the app's domain.

    • (381) Support Flask-Babel 2.0 which has backported Domain support. Flask-Security now supports Flask-Babel (>=2.00), Flask-BabelEx, as well as no translation support. Please see backwards compatibility notes below.

    • (352) Fix issue with adding/deleting permissions - all mutating methods must be at the datastore layer so that db.put() can be called. Added .UserDatastore.add_permissions_to_role and .UserDatastore.remove_permissions_from_role. The methods .RoleMixin.add_permissions and .RoleMixin.remove_permissions have been deprecated.

      1. Provide ability to change table names for User and Role tables in the fsqla model.

    • (338) All sessions are invalidated when a user changes or resets their password. This is accomplished by changing the user's fs_uniquifier. The user is automatically re-logged in (and a new session created) after a successful change operation.

    • (418) Two-factor (and to a lesser extent unified sign in) QRcode fetching wasn't protected via CSRF. The fix makes things secure and simpler (always good); however read below for compatibility concerns. In addition, the elements that make up the QRcode (key, username, issuer) area also made available to the form and returned as part of the JSON return value - this allows for manual or other ways to initialize the authenticator app.

    • (421) GET on /login and /change could return the callers authentication_token. This is a security concern since GETs don't have CSRF protection. This bug was introduced in 3.3.0.

    Backwards Compatibility Concerns

    • (328) Remove dependence on Flask-Mail and refactor. The send_mail_task and send_mail methods as part of Flask-Security initialization have been removed and replaced with a new .MailUtil class. The utility method .send_mail can still be used. If your application didn't use either of the deprecated methods, then the only change required is to add Flask-Mail to your package requirements (since Flask-Security no longer lists it). Please see the emails_topic for updated examples.

    • (335) Convert two-factor setup flow to use the freshness feature rather than its own verify password endpoint. This COMPLETELY removes the /tf-confirm endpoint and associated form: two_factor_verify_password_form. Now, when /tf-setup is invoked, the flask_security.check_and_update_authn_fresh is invoked, and if the current session isn't 'fresh' the caller will be redirected to a verify endpoint (either SECURITY_VERIFY_URL or SECURITY_US_VERIFY_URL). The simplest change would be to call /verify everywhere the application used to call /tf-confirm.

    • (339) Require fs_uniquifier. In 3.3 the fs_uniquifier was added in the UserModel to fix the slow authentication token issue. In 3.4 the fs_uniquifier was used to implement Flask-Login's Alternative Token feature - thus decoupling the primary key (id) from any security context. All along, there have been a few issues with applications not wanting to use the name 'id' in their model, or wanting a different type for their primary key. With this change, Flask-Security no longer interprets or uses the UserModel primary key - just the fs_uniquifier field. See the changes section for 3.3 for information on how to do the schema and data upgrades required to add this field. There is also an API change - the JSON response (via UserModel.get_security_payload()) returned the user.id field. With this change the default is an empty directory - override .UserMixin.get_security_payload() to return any portion of the UserModel you need.

    • (349) SECURITY_USER_IDENTITY_ATTRIBUTES has changed syntax and semantics. It now contains the combined information from the old SECURITY_USER_IDENTITY_ATTRIBUTES and the newly introduced in 3.4 SECURITY_USER_IDENTITY_MAPPINGS. This enabled changing the underlying way we validate credentials in the login form and unified sign in form. In prior releases we simply tried to look up the form value as the PK of the UserModel - this often failed and then looped through the other SECURITY_USER_IDENTITY_ATTRIBUTES. This had a history of issues, including many applications not wanting to have a standard PK for the user model. Now, using the mapping configuration, the UserModel attribute/column the input corresponds to is determined, then the UserModel is queried specifically for that attribute:value pair. If you application didn't change the variable, no modifications are required.

    • (354) The flask_security.PhoneUtil is now initialized as part of Flask-Security initialization rather than @app.before_first_request (since that broke the CLI). Since it isn't called in an application context, the app being initialized is passed as an argument to __init__.

    • (381) When using Flask-Babel (>= 2.0) it is required that the application initialize Flask-Babel (e.g. Babel(app)). Flask-BabelEx would self-initialize so it didn't matter. Flask-Security will throw a run time error upon first request if Flask-Babel OR FLask-BabelEx is installed, but not initialized. Also, Flask-Security no longer has a dependency on either Flask-Babel or Flask-BabelEx - if neither are installed, it falls back to a dummy translation. If your application expects translation services, it must specify the appropriate dependency AND initialize it.

    • (394) Email input is now normalized prior to being stored in the DB. Previously, it was validated, but the raw input was stored. Normalization and validation rely on the email_validator package. The .MailUtil class provides the interface for normalization and validation - allowing all this to be customized. If you have unicode local or domain parts - existing users may have difficulties logging in. Administratively you need to read each user record, normalize the email (see .MailUtil), and write it back.

    • (381) Passwords are now, by default, normalized using Python's unicodedata.normalize() method. The SECURITY_PASSWORD_NORMALIZE_FORM defaults to "NKFD". This brings Flask-Security in line with the NIST recommendations outlined in Memorized Secret Verifiers If your users have unicode passwords they may have difficulty authenticating. You can turn off this normalization or have your users reset their passwords. Password normalization and validation has been encapsulated in a new .PasswordUtil class. This replaces the method password_validator introduced in 3.4.0.

    • (403) By default all forms that have an email as input now use the wtforms html5 EmailField. For most applications this will make the user experience slightly nicer - especially for mobile devices. Some applications use the email form field for other identity attributes (such as username). If your application does this you will probably need to subclass LoginForm and change the email type back to StringField.

    • (338) By default, both passwords and authentication tokens use the same attribute fs_uniquifier to uniquely identify the user. This means that if the user changes or resets their password, all authentication tokens also become invalid. This could be viewed as a feature or a bug. If this behavior isn't desired, add another uniquifier: fs_token_uniquifier to your UserModel and that will be used to generate authentication tokens.

    • (418) Fix CSRF vulnerability w.r.t. getting QRcodes. Both two-factor and unified-signup had a separate GET endpoint to fetch the QRcode when setting up an authenticator app. GETS don't have any CSRF protection. Both of those endpoints have been completely removed, and the QRcode is embedded in a successful POST of the setup form. The changes to the templates are minimal and of course if you didn't override the template - there is no compatibility concern.

    • (421) Fix CSRF vulnerability on /login and /change that could return the callers authentication token. Now, callers can only get the authentication token on successful POST calls.

    Open source →
  36. 4.0.0rc19 Oct 2020pre-release

    Nothing published for this version

  37. 3.4.58 Jan 2021
    Release notes

    Released January 8, 2021

    Security Vulnerability Fix.

    Two CSRF vulnerabilities were reported: qrcode and login. This release fixes the more severe of the 2 - the /login vulnerability. The QRcode issue has a much smaller risk profile since a) it is only for two-factor authentication using an authenticator app b) the qrcode is only available during the time the user is first setting up their authentication app. The QRcode issue has been fixed in 4.0.

    Fixed

    • (421) GET on /login and /change could return the callers authentication_token. This is a security concern since GETs don't have CSRF protection. This bug was introduced in 3.3.0.

    Backwards Compatibility Concerns

    • (421) Fix CSRF vulnerability on /login and /change that could return the callers authentication token. Now, callers can only get the authentication token on successful POST calls.

    Open source →
  38. 3.4.428 Jul 2020
    Release notes

    Released July 27, 2020

    Bug/regression fixes.

    Fixed

    • (359) Basic Auth broken. When the unauthenticated handler was changed to provide a more uniform/consistent response - it broke using Basic Auth from a browser, since it always redirected rather than returning 401. Now, if the response headers contain WWW-Authenticate (which is set if basic @auth_required method is used), a 401 is returned. See below for backwards compatibility concerns.

    • (362) As part of figuring out issue 359 - a redirect loop was found. In release 3.3.0 code was put in to redirect to SECURITY_POST_LOGIN_VIEW when GET or POST was called and the caller was already authenticated. The method used would honor the request next query parameter. This could cause redirect loops. The pre-3.3.0 behavior of redirecting to SECURITY_POST_LOGIN_VIEW and ignoring the next parameter has been restored.

    • (347) Fix peewee. Turns out - due to lack of unit tests - peewee hasn't worked since 'permissions' were added in 3.3. Furthermore, changes in 3.4 around get_id and alternative tokens also didn't work since peewee defines its own get_id method.

    Compatibility Concerns

    In 3.3.0, flask_security.auth_required was changed to add a default argument if none was given. The default include all current methods - session, token, and basic. However basic really isn't like the others and requires that we send back a WWW-Authenticate header if authentication fails (and return a 401 and not redirect). basic has been removed from the default set and must once again be explicitly requested.

    Open source →
  39. 3.4.313 Jun 2020
    Release notes

    Released June 12, 2020

    Minor fixes for a regression and a couple other minor changes

    Fixed

      1. Fix regression where tf_phone_number was required, even if SMS wasn't configured.

      1. Pick up some small documentation fixes from 4.0.0.

    Open source →
  40. 3.4.23 May 2020
    Release notes

    Released May 2, 2020

    Only change is to move repo to the Flask-Middleware github organization.

    Open source →
  41. 3.4.122 Apr 2020
    Release notes

    Released April 22, 2020

    Fix a bunch of bugs in new unified sign in along with a couple other major issues.

    Fixed

      1. Alternative ID feature ran afoul of postgres/psycopg2 finickiness.

    • (300) JSON 401 responses had WWW-Authenticate Header attached - that caused browsers to pop up their own login/password form. Not what applications want.

    • (280) Allow admin/api to setup TFA (and unified sign in) out of band. Please see .UserDatastore.tf_set, .UserDatastore.tf_reset, .UserDatastore.us_set, .UserDatastore.us_reset and .UserDatastore.reset_user_access.

    • (305) We used form._errors which wasn't very pythonic, and it was removed in WTForms 2.3.0.

      1. WTForms 2.3.0 made email_validator optional - we need it.

    Open source →
  42. 3.4.031 Mar 2020
    Release notes

    Released March 31, 2020

    Features

      1. Support a unified sign in feature. Please see configuration:unified signin.

    • (265) Add phone number validation class. This is used in both unified sign in as well as two-factor when using sms.

    • (274) Add support for 'freshness' of caller's authentication. This permits endpoints to be additionally protected by ensuring a recent authentication.

    • (99, 195) Support pluggable password validators. Provide a default validator that offers complexity and breached support.

    • (266) Provide interface to two-factor send_token so that applications can provide error mitigation. Defaults to returning errors if can't send the verification code.

    • (247) Updated all-inclusive data models (fsqlaV2). Add fields necessary for the new unified sign in feature and changed 'username' to be unique (but not required).

    • (245) Use fs_uniquifier as the default Flask-Login 'alternative token'. Basically this means that changing the fs_uniquifier will cause outstanding auth tokens, session and remember me cookies to be invalidated. So if an account gets compromised, an admin can easily stop access. Prior to this cookies were storing the 'id' which is the user's primary key - difficult to change! (kishi85)

    Fixed

      1. Don't allow reset password for accounts that are disabled.

    • (282) Add configuration that disallows GET for logout. Allowing GET can cause some denial of service issues. The default still allows GET for backwards compatibility. (kantorii)

    • (258) Reset password wasn't integrated into the two-factor feature and therefore two-factor auth could be bypassed.

      1. Allow lists and sets as underlying permissions. (pffs)

    • (251) Allow a registration form to have additional fields that aren't part of the user model that are just passed to the user_registered.send signal, where the application can perform arbitrary additional actions required during registration. (kuba-lilz)

      1. Add configuration to disable the 'role-joining' optimization for SQLAlchemy. (pffs)

      1. Fix more issues with atomically setting the new TOTP secret when setting up two-factor. (kishi85)

      1. Fix Quart Compatibility. (ristellise)

      1. CSRF Cookie not being set when using 'Remember Me' cookie to re-sign in. (kishi85)

      1. Two-factor enabled accounts didn't work with the Remember Me feature. (kishi85)

    As part of adding unified sign in, there were many similarities with two-factor. Some refactoring was done to unify naming, configuration variables etc. It should all be backwards compatible.

    • In TWO_FACTOR_ENABLED_METHODS "mail" was changed to "email". "mail" will still be honored if already stored in DB. Also "google_authenticator" is now just "authenticator".

    • TWO_FACTOR_SECRET, TWO_FACTOR_URI_SERVICE_NAME, TWO_FACTOR_SMS_SERVICE, and TWO_FACTOR_SMS_SERVICE_CONFIG have all been deprecated in favor of names that are the same for two-factor and unified sign in.

    Other changes with possible backwards compatibility issues:

    • /tf-setup never did any phone number validation. Now it does.

    • two_factor_setup.html template - the chosen_method check was changed to email. If you have your own custom template - be sure make that change.

    Open source →
  43. 3.3.311 Feb 2020
    Release notes

    Released February 11, 2020

    Minor changes required to work with latest released Werkzeug and Flask-Login.

    Open source →
  44. 3.3.26 Dec 2019
    Release notes

    Released December 7, 2019

      1. Fixed 2FA totp secret regeneration bug (kishi85)

      1. Fixed 'next' redirect error in login view

    • (221) Fixed regressions in login view when already authenticated user again does a GET or POST.

      1. Added example code for unit testing FS protected routes.

      1. Integrated two-factor auth into registration and confirmation.

    Thanks to kuba-lilz and kishi85 for finding and providing detailed issue reports.

    In Flask-Security 3.3.0 the login view was changed to allow already authenticated users to access the view. Prior to 3.3.0, the login view was protected with @anonymous_user_required - so any access (via GET or POST) would simply redirect the user to the POST_LOGIN_VIEW. With the 3.3.0 changes, both GET and POST behaved oddly. GET simply returned the login template, and POST attempted to log out the current user, and log in the new user. This was problematic since this couldn't possibly work with CSRF. The old behavior has been restored, with the subtle change that older Flask-Security releases did not look at "next" in the form or request for the redirect, and now, all redirects from the login view will honor "next".

    Open source →
  45. 3.3.118 Nov 2019
    Release notes

    Released November 16, 2019

      1. Add Quart compatibility (Ristellise)

      1. Add Python 3.8 support into CI (jdevera)

      1. Improve docs around Single Page Applications and React (acidjunk)

    • (201) fsqla model was added to __init__.py making Sqlalchemy a required package. That is wrong and has been removed. Applications must now explicitly import from flask_security.models

    • (204) Fix/improve examples and quickstart to show one MUST call hash_password() when creating users programmatically. Also show real SECRET_KEYs and PASSWORD_SALTs and how to generate them.

      1. Add argon2 as an allowable password hash.

    • (210) Improve integration with Flask-Admin. Actually - this PR improves localization support by adding a method _fsdomain to jinja2's global environment. Added documentation around localization.

    Open source →
  46. 3.3.026 Sept 2019
    Release notes

    Released September 26, 2019

    There are several default behavior changes that might break existing applications. Most have configuration variables that restore prior behavior.

    If you use Authentication Tokens (rather than session cookies) you MUST make a (small) change. Please see below for details.

    • (120) Native support for Permissions as part of Roles. Endpoints can be protected via permissions that are evaluated based on role(s) that the user has.

    • (126, 93, 96) Revamp entire CSRF handling. This adds support for Single Page Applications and having CSRF protection for browser(session) authentication but ignored for token based authentication. Add extensive documentation about all the options.

      1. Token authentication is slow. Please see below for details on how to enable a new, fast implementation.

    • (130) Enable applications to provide their own .render_json method so that they can create unified API responses.

    • (121) Unauthorized callback not quite right. Split into 2 different callbacks - one for unauthorized and one for unauthenticated. Made default unauthenticated handler use Flask-Login's unauthenticated method to make everything uniform. Extensive documentation added. .Security.unauthorized_callback has been deprecated.

    • (120) Add complete User and Role model mixins that support all features. Modify tests and Quickstart documentation to show how to use these. Please see responsetopic for details.

    • Improve documentation for .UserDatastore.create_user to make clear that hashed password should be passed in.

    • Improve documentation for .UserDatastore and .verify_and_update_password to make clear that caller must commit changes to DB if using a session based datastore.

      1. Clarify when to use confirm_register_form rather than register_form.

    • Fix bug in 2FA that didn't commit DB after using verify_and_update_password.

    • Fix bug(s) in UserDatastore where changes to user active flag weren't being added to DB.

      1. JSON response was failing due to LazyStrings in error response.

      1. Making a user inactive should stop all access immediately.

    • (134) Confirmation token can no longer be reused. Added SECURITY_AUTO_LOGIN_AFTER_CONFIRM option for applications that don't want the user to be automatically logged in after confirmation (defaults to True - existing behavior).

    • (159) The /register endpoint returned the Authentication Token even though confirmation was required. This was a huge security hole - it has been fixed.

      1. The 2FA totp_secret would be regenerated upon submission, making QRCode not work. (malware-watch)

      1. default_render_json uses flask.make_response and forces the Content-Type to JSON for generating the response (koekie)

      1. SECURITY_MSG_UNAUTHENTICATED added to the configuration.

    • (168) When using the @auth_required or @auth_token_required decorators, the token would be verified twice, and the DB would be queried twice for the user. Given how slow token verification is - this was a significant issue. That has been fixed.

    • (84) The .anonymous_user_required was not JSON friendly - always performing a redirect. Now, if the request 'wants' a JSON response - it will receive a 400 with an error message defined by SECURITY_MSG_ANONYMOUS_USER_REQUIRED.

      1. Improve 2FA templates to that they can be localized. (taavie)

    • (173) SECURITY_UNAUTHORIZED_VIEW didn't accept a url (just an endpoint). All other view configurations did. That has been fixed.

    Possible compatibility issues

    • (164) In prior releases, the Authentication Token was returned as part of the JSON response to each successful call to /login, /change, or /reset/{token} API call. This is not a great idea since for browser-based UIs that used JSON request/response, and used session based authentication - they would be sent this token - even though it was likely ignored. Since these tokens by default have no expiration time this exposed a needless security hole. The new default behavior is to ONLY return the Authentication Token from those APIs if the query param include_auth_token is added to the request. Prior behavior can be restored by setting the SECURITY_BACKWARDS_COMPAT_AUTH_TOKEN configuration variable.

    • (120) .RoleMixin now has a method .get_permissions which is called as part each request to add Permissions to the authenticated user. It checks if the RoleModel has a property permissions and assumes it is a comma separated string of permissions. If your model already has such a property this will likely fail. You need to override .get_permissions and simply return an emtpy set.

    • (121) Changes the default (failure) behavior for views protected with @auth_required, @token_auth_required, or @http_auth_required. Before, a 401 was returned with some stock html. Now, Flask-Login.unauthorized() is called (the same as @login_required does) - which by default redirects to a login page/view. If you had provided your own .Security.unauthorized_callback there are no changes - that will still be called first. The old default behavior can be restored by setting SECURITY_BACKWARDS_COMPAT_UNAUTHN to True. Please see responsetopic for details.

    • (127) Fix for LazyStrings in json error response. The fix for this has Flask-Security registering its own JsonEncoder on its blueprint. If you registered your own JsonEncoder for your app - it will no longer be called when serializing responses to Flask-Security endpoints. You can register your JsonEncoder on Flask-Security's blueprint by sending it as json_encoder_cls as part of initialization. Be aware that your JsonEncoder needs to handle LazyStrings (see speaklater).

    • (84) Prior to this fix - anytime the decorator .anonymous_user_required failed, it caused a redirect to the post_login_view. Now, if the caller wanted a JSON response, it will return a 400.

      1. Faster Authentication Token introduced the following non-backwards compatible behavior change:

      • Since the old Authentication Token algorithm used the (hashed) user's password, those tokens would be invalidated whenever the user changed their password. This is not likely to be what most users expect. Since the new Authentication Token algorithm doesn't refer to the user's password, changing the user's password won't invalidate outstanding Authentication Tokens. The method .UserDatastore.set_uniquifier can be used by an administrator to change a user's fs_uniquifier - but nothing the user themselves can do to invalidate their Authentication Tokens. Setting the SECURITY_BACKWARDS_COMPAT_AUTH_TOKEN_INVALIDATE configuration variable will cause the user's fs_uniquifier to be changed when they change their password, thus restoring prior behavior.

    New fast authentication token implementation

    Current auth tokens are slow because they use the user's password (hashed) as a uniquifier (the user id isn't really enough since it might be reused). This requires checking the (hashed) password against what is in the token on EVERY request - however hashing is (on purpose) slow. So this can add almost a whole second to every request.

    To solve this, a new attribute in the User model was added - fs_uniquifier. If this is present in your User model, then it will be used instead of the password for ensuring the token corresponds to the correct user. This is very fast. If that attribute is NOT present - then the behavior falls back to the existing (slow) method.

    DB Migration

    To use the new UserModel mixins or to add the column user.fs_uniquifier to speed up token authentication, a schema AND data migration needs to happen. If you are using Alembic the schema migration is easy - but you need to add fs_uniquifier values to all your existing data. You can add code like this to your migrations::update method:

    # be sure to MODIFY this line to make nullable=True:
    op.add_column('user', sa.Column('fs_uniquifier', sa.String(length=64), nullable=True))
    
    # update existing rows with unique fs_uniquifier
    import uuid
    user_table = sa.Table('user', sa.MetaData(), sa.Column('id', sa.Integer, primary_key=True),
                          sa.Column('fs_uniquifier', sa.String))
    conn = op.get_bind()
    for row in conn.execute(sa.select([user_table.c.id])):
        conn.execute(user_table.update().values(fs_uniquifier=uuid.uuid4().hex).where(user_table.c.id == row['id']))
    
    # finally - set nullable to false
    op.alter_column('user', 'fs_uniquifier', nullable=False)
    
    # for MySQL the previous line has to be replaced with...
    # op.alter_column('user', 'fs_uniquifier', existing_type=sa.String(length=64), nullable=False)
    Open source →
  47. 3.3.0rc313 Sept 2019pre-release

    Nothing published for this version

  48. 3.3.0rc25 Aug 2019pre-release

    Nothing published for this version

  49. 3.3.0rc123 Jul 2019pre-release

    Nothing published for this version

  50. 3.2.027 Jun 2019
    Release notes

    Released June 26th 2019

    • (80) Support caching of authentication token (eregnier opr #839). This adds a new configuration variable SECURITY_USE_VERIFY_PASSWORD_CACHE which enables a cache (with configurable TTL) for authentication tokens. This is a big performance boost for those accessing Flask-Security via token as opposed to session.

    • (81) Support for JSON/Single-Page-Application. This completes support for non-form based access to Flask-Security. See PR for details. (jwag956)

    • (79 Add POST logout to enhance JSON usage (jwag956).

    • (73) Fix get_user for various DBs (jwag956). This is a more complete fix than in opr #633.

    • (78, 103) Add formal openapi API spec (jwag956).

    • (86, 94, 98, 101, 104) Add Two-factor authentication (opr #842) (baurt, jwag956).

      1. Fix form field label translations (jwag956)

      1. Fix form error message translations (upstream #801) (jwag956)

      1. Convert entire repo to Black (baurt)

    Open source →
  51. 3.2.0rc424 Jun 2019pre-release

    Nothing published for this version

  52. 3.2.0rc313 Jun 2019pre-release

    Nothing published for this version

  53. 3.2.0rc128 May 2019pre-release

    Nothing published for this version

  54. 3.1.0rc112 May 2019pre-release

    Nothing published for this version

  55. 3.0.21 May 2019
    Release notes

    Released April 30th 2019

    • (opr #439) HTTP Auth respects SECURITY_USER_IDENTITY_ATTRIBUTES (pnpnpn)

    • (opr #660) csrf_enabled` deprecation fix (abulte)

    • (opr #671) Fix referrer loop in _get_unauthorized_view(). (nfvs)

    • (opr #675) Fix AttributeError in _request_loader (sbagan)

    • (opr #676) Fix timing attack on login form (cript0nauta)

    • (opr #683) Close db connection after running tests (reambus)

    • (opr #691) docs: add password salt to SQLAlchemy app example (KshitijKarthick)

    • (opr #692) utils: fix incorrect email sender type (switowski)

    • (opr #696) Fixed broken Click link (williamhatcher)

    • (opr #722) Fix password recovery confirmation on deleted user (kesara)

    • (opr #747) Update login_user.html (rickwest)

    • (opr #748) i18n: configurable the dirname domain (escudero)

    • (opr #835) adds relevant user to reset password form for validation purposes (fuhrysteve)

    These are bug fixes and a couple very small additions. No change in behavior and no new functionality. 'opr#' is the original pull request from https://github.com/mattupstate/flask-security

    Open source →
  56. 3.0.128 Apr 2019
    Release notes

    Released April 28th 2019

    • Support 3.7 as part of CI

    • Rebrand to this forked repo

    • (#15) Build docs and translations as part of CI

    • (#17) Move to msgcheck from pytest-translations

    • (opr #669) Fix for Read the Docs (jirikuncar)

    • (opr #710) Spanish translation (maukoquiroga)

    • (opr #712) i18n: improvements of German translations (eseifert)

    • (opr #713) i18n: add Portuguese (Brazilian) translation (dinorox)

    • (opr #719) docs: fix anchor links and typos (kesara)

    • (opr #751) i18n: fix missing space (abulte)

    • (opr #762) docs: fixed proxy import (lsmith)

    • (opr #767) Update customizing.rst (allanice001)

    • (opr #776) i18n: add Portuguese (Portugal) translation (micael-grilo)

    • (opr #791) Fix documentation for mattupstate#781 (fmerges)

    • (opr #796) Chinese translations (Steinkuo)

    • (opr #808) Clarify that a commit is needed after login_user (christophertull)

    • (opr #823) Add Turkish translation (Admicos)

    • (opr #831) Catalan translation (miceno)

    These are all documentation and i18n changes - NO code changes. All except the last 3 were accepted and reviewed by the original Flask-Security team. Thanks as always to all the contributors.

    Open source →
  57. 3.0.1rc328 Apr 2019pre-release

    Nothing published for this version

  58. 3.0.1rc225 Apr 2019pre-release

    Nothing published for this version

  59. 3.0.1rc125 Apr 2019pre-release

    Nothing published for this version