From d39cfab283f3d5fea35b304a7e4bb9f7b110d5a4 Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Sat, 13 Jul 2019 15:51:34 +0200
Subject: [PATCH] Increase the security of JWT token generation by using
 DJANGO_SECRET_KEY as well as user-specific salt for the signature

---
 api/config/settings/common.py               |  9 ++++++++-
 api/funkwhale_api/federation/serializers.py |  2 +-
 api/tests/users/test_jwt.py                 | 19 +++++++++++++++++++
 changes/changelog.d/jwt.enhancement         |  1 +
 4 files changed, 29 insertions(+), 2 deletions(-)
 create mode 100644 changes/changelog.d/jwt.enhancement

diff --git a/api/config/settings/common.py b/api/config/settings/common.py
index d0ff2e1883..360346b276 100644
--- a/api/config/settings/common.py
+++ b/api/config/settings/common.py
@@ -564,12 +564,19 @@ CELERY_BEAT_SCHEDULE = {
 
 NODEINFO_REFRESH_DELAY = env.int("NODEINFO_REFRESH_DELAY", default=3600 * 24)
 
+
+def get_user_secret_key(user):
+    from django.conf import settings
+
+    return settings.SECRET_KEY + str(user.secret_key)
+
+
 JWT_AUTH = {
     "JWT_ALLOW_REFRESH": True,
     "JWT_EXPIRATION_DELTA": datetime.timedelta(days=7),
     "JWT_REFRESH_EXPIRATION_DELTA": datetime.timedelta(days=30),
     "JWT_AUTH_HEADER_PREFIX": "JWT",
-    "JWT_GET_USER_SECRET_KEY": lambda user: user.secret_key,
+    "JWT_GET_USER_SECRET_KEY": get_user_secret_key,
 }
 OLD_PASSWORD_FIELD_ENABLED = True
 ACCOUNT_ADAPTER = "funkwhale_api.users.adapters.FunkwhaleAccountAdapter"
diff --git a/api/funkwhale_api/federation/serializers.py b/api/funkwhale_api/federation/serializers.py
index 51ee01a81f..ed40017cca 100644
--- a/api/funkwhale_api/federation/serializers.py
+++ b/api/funkwhale_api/federation/serializers.py
@@ -1012,7 +1012,7 @@ class TrackSerializer(MusicEntitySerializer):
         metadata = music_tasks.federation_audio_track_to_metadata(
             validated_data, references
         )
-        metadata['tags'] = tags
+        metadata["tags"] = tags
 
         from_activity = self.context.get("activity")
         if from_activity:
diff --git a/api/tests/users/test_jwt.py b/api/tests/users/test_jwt.py
index 83de757c8b..d0fe1a1fa7 100644
--- a/api/tests/users/test_jwt.py
+++ b/api/tests/users/test_jwt.py
@@ -22,3 +22,22 @@ def test_can_invalidate_token_when_changing_user_secret_key(factories):
     # token should be invalid
     with pytest.raises(DecodeError):
         api_settings.JWT_DECODE_HANDLER(payload)
+
+
+def test_can_invalidate_token_when_changing_settings_secret_key(factories, settings):
+    settings.SECRET_KEY = "test1"
+    user = factories["users.User"]()
+    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
+    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
+    payload = jwt_payload_handler(user)
+    payload = jwt_encode_handler(payload)
+
+    # this should work
+    api_settings.JWT_DECODE_HANDLER(payload)
+
+    # now we update the secret key
+    settings.SECRET_KEY = "test2"
+
+    # token should be invalid
+    with pytest.raises(DecodeError):
+        api_settings.JWT_DECODE_HANDLER(payload)
diff --git a/changes/changelog.d/jwt.enhancement b/changes/changelog.d/jwt.enhancement
new file mode 100644
index 0000000000..0ce222251e
--- /dev/null
+++ b/changes/changelog.d/jwt.enhancement
@@ -0,0 +1 @@
+Increase the security of JWT token generation by using DJANGO_SECRET_KEY as well as user-specific salt for the signature
-- 
GitLab