From 755ffd88154b0eb8d2f0fe6c9e7a443aba6bcfc1 Mon Sep 17 00:00:00 2001 From: tuhin-thinks Date: Sat, 21 Sep 2024 15:57:57 +0530 Subject: [PATCH 1/5] fixed: Handled error when authheader is `Bearer ` with no token-string following up. --- oauth2_provider/middleware.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oauth2_provider/middleware.py b/oauth2_provider/middleware.py index 65c9cf03c..fed06ffde 100644 --- a/oauth2_provider/middleware.py +++ b/oauth2_provider/middleware.py @@ -52,8 +52,8 @@ def __init__(self, get_response): def __call__(self, request): authheader = request.META.get("HTTP_AUTHORIZATION", "") - if authheader.startswith("Bearer"): - tokenstring = authheader.split()[1] + if authheader.startswith("Bearer") and len(authheader.split(maxsplit=1)) == 2: + tokenstring = authheader.split(maxsplit=1)[1] AccessToken = get_access_token_model() try: token_checksum = hashlib.sha256(tokenstring.encode("utf-8")).hexdigest() From 48701120e503c26af7e2e9d5c799476f4dd91e09 Mon Sep 17 00:00:00 2001 From: tuhin-thinks Date: Sat, 21 Sep 2024 15:58:16 +0530 Subject: [PATCH 2/5] included my name in authors --- AUTHORS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index e35ed4cb9..4ebe787cd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -128,4 +128,5 @@ Yaroslav Halchenko Yuri Savin Miriam Forner Alex Kerkum -q0w +Tuhin Mitra +q0w \ No newline at end of file From 76420a1eefe61f1ffb99a49049411c3e611b371a Mon Sep 17 00:00:00 2001 From: tuhin-thinks Date: Sat, 21 Sep 2024 16:16:41 +0530 Subject: [PATCH 3/5] changed CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eadc051d3..a29772c13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> ### Fixed * #1252 Fix crash when 'client' is in token request body +* #1496 Fix error when Bearer token string is empty but preceded by `Bearer` keyword. From afb38a3fd818b843578bf008d0b3fb933e0cb786 Mon Sep 17 00:00:00 2001 From: tuhin-thinks Date: Wed, 2 Oct 2024 23:41:29 +0530 Subject: [PATCH 4/5] changed middleware.py to optimize usage of variables. --- oauth2_provider/middleware.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/oauth2_provider/middleware.py b/oauth2_provider/middleware.py index fed06ffde..5a8a86d87 100644 --- a/oauth2_provider/middleware.py +++ b/oauth2_provider/middleware.py @@ -52,8 +52,9 @@ def __init__(self, get_response): def __call__(self, request): authheader = request.META.get("HTTP_AUTHORIZATION", "") - if authheader.startswith("Bearer") and len(authheader.split(maxsplit=1)) == 2: - tokenstring = authheader.split(maxsplit=1)[1] + splits = authheader.split(maxsplit=1) + if authheader.startswith("Bearer") and len(splits) == 2: + tokenstring = splits[1] AccessToken = get_access_token_model() try: token_checksum = hashlib.sha256(tokenstring.encode("utf-8")).hexdigest() From 10a210afe2f56076effca13fb516dc8873e23b2f Mon Sep 17 00:00:00 2001 From: tuhin-thinks Date: Mon, 10 Nov 2025 02:43:51 +0530 Subject: [PATCH 5/5] test: add unit tests for OAuth2ExtraTokenMiddleware handling of bearer tokens --- tests/test_oauth2_provider_middleware.py | 98 ++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/test_oauth2_provider_middleware.py diff --git a/tests/test_oauth2_provider_middleware.py b/tests/test_oauth2_provider_middleware.py new file mode 100644 index 000000000..90610f78b --- /dev/null +++ b/tests/test_oauth2_provider_middleware.py @@ -0,0 +1,98 @@ +import datetime +import hashlib + +from django.contrib.auth import get_user_model +from django.test import RequestFactory, TestCase + +from oauth2_provider.middleware import OAuth2ExtraTokenMiddleware +from oauth2_provider.models import get_access_token_model, get_application_model + + +Application = get_application_model() +AccessToken = get_access_token_model() +User = get_user_model() + + +class TestOAuth2ExtraTokenMiddleware(TestCase): + def setUp(self): + self.factory = RequestFactory() + self.middleware = OAuth2ExtraTokenMiddleware(lambda r: None) + + # Create test user and application for valid token tests + self.user = User.objects.create_user("test_user", "test@example.com", "123456") + self.application = Application.objects.create( + name="Test Application", + user=self.user, + client_type=Application.CLIENT_CONFIDENTIAL, + authorization_grant_type=Application.GRANT_AUTHORIZATION_CODE, + ) + + def test_malformed_bearer_header_no_token(self): + """Test that 'Authorization: Bearer' without token doesn't crash""" + request = self.factory.get("/", HTTP_AUTHORIZATION="Bearer") + + # This should not raise an IndexError + _ = self.middleware(request) + + # Should not have access_token attribute + self.assertFalse(hasattr(request, "access_token")) + + def test_malformed_bearer_header_empty_token(self): + """Test that 'Authorization: Bearer ' with empty token doesn't crash""" + request = self.factory.get("/", HTTP_AUTHORIZATION="Bearer ") + + # This should not raise an IndexError + _ = self.middleware(request) + + # Should not have access_token attribute + self.assertFalse(hasattr(request, "access_token")) + + def test_valid_bearer_token(self): + """Test that valid bearer token works correctly""" + # Create a valid access token + token_string = "test-token-12345" + token_checksum = hashlib.sha256(token_string.encode("utf-8")).hexdigest() + access_token = AccessToken.objects.create( + user=self.user, + scope="read", + expires=datetime.datetime.now() + datetime.timedelta(days=1), + token=token_string, + token_checksum=token_checksum, + application=self.application, + ) + + request = self.factory.get("/", HTTP_AUTHORIZATION=f"Bearer {token_string}") + + _ = self.middleware(request) + + # Should have access_token attribute set + self.assertTrue(hasattr(request, "access_token")) + self.assertEqual(request.access_token, access_token) + + def test_invalid_bearer_token(self): + """Test that invalid bearer token doesn't crash but doesn't set access_token""" + request = self.factory.get("/", HTTP_AUTHORIZATION="Bearer invalid-token-xyz") + + # This should not raise an exception + _ = self.middleware(request) + + # Should not have access_token attribute + self.assertFalse(hasattr(request, "access_token")) + + def test_no_authorization_header(self): + """Test that request without Authorization header works normally""" + request = self.factory.get("/") + + _ = self.middleware(request) + + # Should not have access_token attribute + self.assertFalse(hasattr(request, "access_token")) + + def test_non_bearer_authorization_header(self): + """Test that non-Bearer authorization headers are ignored""" + request = self.factory.get("/", HTTP_AUTHORIZATION="Basic dXNlcjpwYXNz") + + _ = self.middleware(request) + + # Should not have access_token attribute + self.assertFalse(hasattr(request, "access_token"))