----------------
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)
- (:pr:`328`) Remove dependence on Flask-Mail and refactor.
- (:pr:`335`) Remove two-factor `/tf-confirm` endpoint and use generic `freshness` mechanism.
- (:pr:`336`) Remove ``SECURITY_BACKWARDS_COMPAT_AUTH_TOKEN_INVALID(ATE)``. In addition to
not making sense - the documentation has never been correct.
- (:pr:`339`) Require ``fs_uniquifier`` in the UserModel and stop using/referencing the UserModel
primary key.
- (:pr:`349`) 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 :meth:`.UserMixin.calc_username()`.
- (:pr:`382`) Improvements and documentation for two-factor authentication.
- (:pr:`394`) Add support for email validation and normalization (see :class:`.MailUtil`).
- (:issue:`231`) Normalize unicode passwords (see :class:`.PasswordUtil`).
- (:issue:`391`) Option to redirect to `/confirm` if user hits an endpoint that requires
confirmation. New option :py:data:`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)
- (:issue:`366`) Allow redirects on sub-domains. Please see :py:data:`SECURITY_REDIRECT_ALLOW_SUBDOMAINS`. (willcroft)
- (:pr:`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)
- (:pr:`401`) Add 2FA Validity Window so an application can configure how often the second factor has to be entered. (baurt)
- (:pr:`403`) Add HTML5 Email input types to email fields. This has some backwards compatibility concerns outlined below. (drola)
- (:pr:`413`) Add hy_AM translations. (rudolfamirjanyan)
- (:pr:`410`) Add Basque and fix Spanish translations. (mmozos)
- (:pr:`408`) Polish translations. (kamil559)
- (:pr:`390`) Update ru_RU translations. (TitaniumHocker)
Fixed
+++++
- (:issue:`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.
- (:issue:`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.
- (:pr:`352`) Fix issue with adding/deleting permissions - all mutating methods must be at the datastore layer so that
db.put() can be called. Added :meth:`.UserDatastore.add_permissions_to_role` and :meth:`.UserDatastore.remove_permissions_from_role`.
The methods `.RoleMixin.add_permissions` and `.RoleMixin.remove_permissions` have been deprecated.
- (:issue:`395`) Provide ability to change table names for User and Role tables in the fsqla model.
- (:issue:`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.
- (:issue:`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.
- (:issue:`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
+++++++++++++++++++++++++++++++++
- (:pr:`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 :class:`.MailUtil` class.
The utility method :func:`.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 :ref:`emails_topic` for updated examples.
- (:pr:`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 :meth:`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 :py:data:`SECURITY_VERIFY_URL` or
:py:data:`SECURITY_US_VERIFY_URL`). The simplest change would be to call ``/verify`` everywhere
the application used to call ``/tf-confirm``.
- (:pr:`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 :meth:`.UserMixin.get_security_payload()` to return any portion of the UserModel you need.
- (:pr:`349`) :py:data:`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 :py:data:`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.
- (:pr:`354`) The :class:`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__*.
- (:issue:`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.*
- (:pr:`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 <https://pypi.org/project/email-validator/>`_ package.
The :class:`.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 :class:`.MailUtil`), and write it back.
- (:issue:`381`) Passwords are now, by default, normalized using Python's unicodedata.normalize() method.
The :py:data:`SECURITY_PASSWORD_NORMALIZE_FORM` defaults to "NKFD". This brings Flask-Security
in line with the NIST recommendations outlined in `Memorized Secret Verifiers <https://pages.nist.gov/800-63-3/sp800-63b.html#sec5>`_
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 :class:`.PasswordUtil` class. This replaces
the method ``password_validator`` introduced in 3.4.0.
- (:pr:`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.
- (:issue:`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.
- (:issue:`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.
- (:issue:`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.