From d2c2fb837e9d269305b7a8f064c7180c9ded3ff3 Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Thu, 26 Apr 2018 15:17:51 +0200
Subject: [PATCH] Now support Bearer auth in complement of JWT

---
 api/config/settings/common.py              |  1 +
 api/funkwhale_api/common/auth.py           |  3 --
 api/funkwhale_api/common/authentication.py | 37 ++++++++++++++++++++++
 3 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/api/config/settings/common.py b/api/config/settings/common.py
index de1d653cb9..f1a383c587 100644
--- a/api/config/settings/common.py
+++ b/api/config/settings/common.py
@@ -377,6 +377,7 @@ REST_FRAMEWORK = {
     ),
     'DEFAULT_AUTHENTICATION_CLASSES': (
         'funkwhale_api.common.authentication.JSONWebTokenAuthenticationQS',
+        'funkwhale_api.common.authentication.BearerTokenHeaderAuth',
         'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
         'rest_framework.authentication.SessionAuthentication',
         'rest_framework.authentication.BasicAuthentication',
diff --git a/api/funkwhale_api/common/auth.py b/api/funkwhale_api/common/auth.py
index 75839b9366..faf13571d6 100644
--- a/api/funkwhale_api/common/auth.py
+++ b/api/funkwhale_api/common/auth.py
@@ -29,9 +29,6 @@ class TokenHeaderAuth(BaseJSONWebTokenAuthentication):
 
 
 class TokenAuthMiddleware:
-    """
-    Custom middleware (insecure) that takes user IDs from the query string.
-    """
 
     def __init__(self, inner):
         # Store the ASGI application we were passed
diff --git a/api/funkwhale_api/common/authentication.py b/api/funkwhale_api/common/authentication.py
index b75f3b516d..c7566eac8b 100644
--- a/api/funkwhale_api/common/authentication.py
+++ b/api/funkwhale_api/common/authentication.py
@@ -1,3 +1,6 @@
+from django.utils.encoding import smart_text
+from django.utils.translation import ugettext as _
+
 from rest_framework import exceptions
 from rest_framework_jwt import authentication
 from rest_framework_jwt.settings import api_settings
@@ -18,3 +21,37 @@ class JSONWebTokenAuthenticationQS(
     def authenticate_header(self, request):
         return '{0} realm="{1}"'.format(
             api_settings.JWT_AUTH_HEADER_PREFIX, self.www_authenticate_realm)
+
+
+class BearerTokenHeaderAuth(
+        authentication.BaseJSONWebTokenAuthentication):
+    """
+    For backward compatibility purpose, we used Authorization: JWT <token>
+    but Authorization: Bearer <token> is probably better.
+    """
+    www_authenticate_realm = 'api'
+
+    def get_jwt_value(self, request):
+        auth = authentication.get_authorization_header(request).split()
+        auth_header_prefix = 'bearer'
+
+        if not auth:
+            if api_settings.JWT_AUTH_COOKIE:
+                return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
+            return None
+
+        if smart_text(auth[0].lower()) != auth_header_prefix:
+            return None
+
+        if len(auth) == 1:
+            msg = _('Invalid Authorization header. No credentials provided.')
+            raise exceptions.AuthenticationFailed(msg)
+        elif len(auth) > 2:
+            msg = _('Invalid Authorization header. Credentials string '
+                    'should not contain spaces.')
+            raise exceptions.AuthenticationFailed(msg)
+
+        return auth[1]
+
+    def authenticate_header(self, request):
+        return '{0} realm="{1}"'.format('Bearer', self.www_authenticate_realm)
-- 
GitLab