File CVE-2021-21241-GET-reqs-auth-token.patch of Package python-Flask-Security-Too

From 3442e0b73532634e1b8b81d60038301ebc0707fd Mon Sep 17 00:00:00 2001
From: jwag956 <jwag.wagner@gmail.com>
Date: Fri, 1 Jan 2021 19:25:53 -0800
Subject: [PATCH] Fix security vuln - GET on /login or /change could reveal
 authentication token with no CSRF checks.

GETs no longer return the auth token.

closes: #421
---
 flask_security/views.py |   23 +++++++++++++----------
 tests/test_common.py    |   23 +++++++++++++++++++++++
 2 files changed, 36 insertions(+), 10 deletions(-)

--- a/flask_security/views.py
+++ b/flask_security/views.py
@@ -182,13 +182,14 @@ def login():
         login_user(form.user, remember=remember_me, authn_via=["password"])
         after_this_request(_commit)
 
-        if not _security._want_json(request):
-            return redirect(get_post_login_redirect())
+        if _security._want_json(request):
+            return base_render_json(form, include_auth_token=True)
+        return redirect(get_post_login_redirect())
 
     if _security._want_json(request):
         if current_user.is_authenticated:
             form.user = current_user
-        return base_render_json(form, include_auth_token=True)
+        return base_render_json(form)
 
     if current_user.is_authenticated:
         # Basically a no-op if authenticated - just perform the same
@@ -625,16 +626,18 @@ def change_password():
     if form.validate_on_submit():
         after_this_request(_commit)
         change_user_password(current_user._get_current_object(), form.new_password.data)
-        if not _security._want_json(request):
-            do_flash(*get_message("PASSWORD_CHANGE"))
-            return redirect(
-                get_url(_security.post_change_view)
-                or get_url(_security.post_login_view)
-            )
+        if _security._want_json(request):
+            form.user = current_user
+            return base_render_json(form, include_auth_token=True)
+
+        do_flash(*get_message("PASSWORD_CHANGE"))
+        return redirect(
+            get_url(_security.post_change_view) or get_url(_security.post_login_view)
+        )
 
     if _security._want_json(request):
         form.user = current_user
-        return base_render_json(form, include_auth_token=True)
+        return base_render_json(form)
 
     return _security.render_template(
         config_value("CHANGE_PASSWORD_TEMPLATE"),
--- a/tests/test_common.py
+++ b/tests/test_common.py
@@ -724,3 +724,26 @@ def test_session_query(in_app_context):
     assert response.status_code == 200
     end_nqueries = get_num_queries(app.security.datastore)
     assert current_nqueries is None or end_nqueries == (current_nqueries + 2)
+
+
+@pytest.mark.changeable()
+def test_no_get_auth_token(app, client):
+    # Test that GETs don't return an auth token. This is a security issue since
+    # GETs aren't protected with CSRF
+    authenticate(client)
+    response = client.get(
+        "/login?include_auth_token", headers={"Content-Type": "application/json"}
+    )
+    assert "authentication_token" not in response.json["response"]["user"]
+
+    data = dict(
+        password="password",
+        new_password="new strong password",
+        new_password_confirm="new strong password",
+    )
+    response = client.get(
+        "/change?include_auth_token",
+        json=data,
+        headers={"Content-Type": "application/json"},
+    )
+    assert "authentication_token" not in response.json["response"]["user"]
openSUSE Build Service is sponsored by