diff --git a/CHANGES.rst b/CHANGES.rst index 0806a785..eaed6e2a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,6 +3,22 @@ Flask-Security Changelog Here you can see the full list of changes between each Flask-Security release. +Version 5.3.1 +------------- + +Released October XX, 2023 + +Please Note: py_webauthn is pinned to 1.9.0 until the issue with user_handle +is resolved. + +Fixes +++++++ + +- (:issue:`829`) Revert change in 5.3.0 that added a Referrer-Policy header. +- (:issue:`826`) Fix error in quickstart (codycollier) +- (:pr:`835`) Update Armenian translations (amkrtchyan-tmp) +- (:pr:`831`) Update German translations. (sr-verde) + Version 5.3.0 ------------- @@ -51,7 +67,7 @@ Backwards Compatibility Concerns - The SECURITY_MSG_PASSWORD_RESET_EXPIRED message no longer contains the user's identity/email. - The default for :py:data:`SECURITY_RESET_PASSWORD_WITHIN` has been changed from `5 days` to `1 days`. - The response to GET /reset/ sets the HTTP header `Referrer-Policy` to `no-referrer` as suggested - by OWASP. + 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 @@ -63,7 +79,7 @@ Backwards Compatibility Concerns 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/ sets the HTTP header `Referrer-Policy` to `no-referrer` as suggested - by OWASP. + by OWASP. *PLEASE NOTE: this was backed out in 5.3.1* Version 5.2.0 ------------- @@ -200,7 +216,7 @@ Fixes Version 5.0.0 ------------- -Released August 27. 2022 +Released August 27, 2022 **PLEASE READ CHANGE NOTES CAREFULLY - THERE ARE LIKELY REQUIRED CHANGES YOU WILL HAVE TO MAKE.** diff --git a/flask_security/views.py b/flask_security/views.py index e1db74d7..79f973a1 100644 --- a/flask_security/views.py +++ b/flask_security/views.py @@ -462,23 +462,17 @@ def confirm_email(token): if _security.redirect_behavior == "spa": # No reason to expose identity info to anyone who has the link - return ( - redirect( - get_url( - _security.confirm_error_view, - qparams={c: m}, - ) - ), - {"Referrer-Policy": "no-referrer"}, + return redirect( + get_url( + _security.confirm_error_view, + qparams={c: m}, + ) ) do_flash(m, c) - return ( - redirect( - get_url(_security.confirm_error_view) - or url_for_security("send_confirmation") - ), - {"Referrer-Policy": "no-referrer"}, + return redirect( + get_url(_security.confirm_error_view) + or url_for_security("send_confirmation") ) confirm_user(user) @@ -500,30 +494,22 @@ def confirm_email(token): ) if response: do_flash(m, c) - return response, {"Referrer-Policy": "no-referrer"} + return response login_user(user, authn_via=["confirm"]) if _security.redirect_behavior == "spa": - return ( - redirect( - get_url( - _security.post_confirm_view, - qparams=user.get_redirect_qparams({c: m}), - ) - ), - {"Referrer-Policy": "no-referrer"}, + return redirect( + get_url( + _security.post_confirm_view, + qparams=user.get_redirect_qparams({c: m}), + ) ) do_flash(m, c) - return ( - redirect( - get_url(_security.post_confirm_view) - or get_url( - _security.post_login_view - if cv("AUTO_LOGIN_AFTER_CONFIRM") - else ".login" - ) - ), - {"Referrer-Policy": "no-referrer"}, + return redirect( + get_url(_security.post_confirm_view) + or get_url( + _security.post_login_view if cv("AUTO_LOGIN_AFTER_CONFIRM") else ".login" + ) ) @@ -616,26 +602,19 @@ def reset_password(token): # Still - don't include PII such as identity and email if someone # intercepts link they still won't necessarily know the login identity # (even though they can change the password!). - # OWASP recommends setting no-referrer for requests with tokens. if _security.redirect_behavior == "spa": - return ( - redirect( - get_url( - _security.reset_view, - qparams={"token": token}, - ) - ), - {"Referrer-Policy": "no-referrer"}, + return redirect( + get_url( + _security.reset_view, + qparams={"token": token}, + ) ) # for forms - render the reset password form - return ( - _security.render_template( - cv("RESET_PASSWORD_TEMPLATE"), - reset_password_form=form, - reset_password_token=token, - **_ctx("reset_password"), - ), - {"Referrer-Policy": "no-referrer"}, + return _security.render_template( + cv("RESET_PASSWORD_TEMPLATE"), + reset_password_form=form, + reset_password_token=token, + **_ctx("reset_password"), ) # This is the POST case. diff --git a/tests/test_confirmable.py b/tests/test_confirmable.py index 7d2f2a8f..f8e1391e 100644 --- a/tests/test_confirmable.py +++ b/tests/test_confirmable.py @@ -89,7 +89,6 @@ def on_instructions_sent(app, **kwargs): token = registrations[0]["confirm_token"] response = clients.get("/confirm/" + token, follow_redirects=False) assert len(recorded_confirms) == 1 - assert response.headers.get("Referrer-Policy", None) == "no-referrer" response = clients.get(response.location) assert get_message("EMAIL_CONFIRMED") in response.data # make sure not logged in @@ -361,7 +360,6 @@ def test_confirm_redirect_to_post_confirm(client, get_message): response = client.get("/confirm/" + token, follow_redirects=False) assert "/post_confirm" in response.location - assert response.headers.get("Referrer-Policy", None) == "no-referrer" @pytest.mark.registerable() @@ -393,7 +391,6 @@ def test_spa_get(app, client, get_message): assert "/confirm-redirect" == split.path qparams = dict(parse_qsl(split.query)) assert qparams["email"] == "dude@lp.com" - assert response.headers.get("Referrer-Policy", None) == "no-referrer" response = client.get("/confirm/" + token) split = urlsplit(response.headers["Location"]) @@ -402,7 +399,6 @@ def test_spa_get(app, client, get_message): assert "/confirm-error" in response.location assert "email" not in qparams assert get_message("ALREADY_CONFIRMED") in qparams["info"].encode("utf-8") - assert response.headers.get("Referrer-Policy", None) == "no-referrer" # Arguably for json we shouldn't have any - this is buried in register_user # but really shouldn't be. diff --git a/tests/test_recoverable.py b/tests/test_recoverable.py index 1fc98142..20fbc162 100644 --- a/tests/test_recoverable.py +++ b/tests/test_recoverable.py @@ -63,8 +63,6 @@ def on_instructions_sent(app, **kwargs): # Test view for reset token response = clients.get("/reset/" + token) assert b"

Reset password

" in response.data - # OWASP recommends setting this - assert response.headers.get("Referrer-Policy", None) == "no-referrer" # Test submitting a new password but leave out confirm response = clients.post( @@ -460,8 +458,6 @@ def test_spa_get(app, client): response = client.get("/reset/" + token) assert response.status_code == 302 - # OWASP recommends setting this - assert response.headers.get("Referrer-Policy", None) == "no-referrer" split = urlsplit(response.headers["Location"]) assert "localhost:8081" == split.netloc assert "/reset-redirect" == split.path