Repository: jazzband/django-oauth-toolkit

Issue:
Accessing client/application from request
Debugging some OAuth-authenticated request, I noticed that it passes by this line:
https://github.com/jazzband/django-oauth-toolkit/blob/492a867499b50f348c28db4ef3e429e8f46dc412/oauth2_provider/oauth2_validators.py#L426

Although I can read `request.user` inside my "protected" views, the `client` attribute is not available on request.

I'd like to log some actions, registering the application the user authorized to make these actions.... Is it possible?





Discussion:
Well, not sure it's the best way but I think you can do something like this

```python
from oauth2_provider.models import AccessToken

token_header = request.META['HTTP_AUTHORIZATION']
code = re.search('(?<=Bearer ).*', token_header).group(0)
client = AccessToken.objects.get(token=code).application
```
@femesq , This might be a nice middleware addition.  Care to create a PR? 
Would be very happy to contribute to this... Will start studying how middleware works and work on this PR soon...

Resolving patch:
diff --git a/oauth2_provider/middleware.py b/oauth2_provider/middleware.py
--- a/oauth2_provider/middleware.py
+++ b/oauth2_provider/middleware.py
@@ -1,6 +1,13 @@
+import logging
+
 from django.contrib.auth import authenticate
 from django.utils.cache import patch_vary_headers
 
+from oauth2_provider.models import AccessToken
+
+
+log = logging.getLogger(__name__)
+
 
 class OAuth2TokenMiddleware:
     """
@@ -36,3 +43,20 @@ def __call__(self, request):
         response = self.get_response(request)
         patch_vary_headers(response, ("Authorization",))
         return response
+
+
+class OAuth2ExtraTokenMiddleware:
+    def __init__(self, get_response):
+        self.get_response = get_response
+
+    def __call__(self, request):
+        authheader = request.META.get("HTTP_AUTHORIZATION", "")
+        if authheader.startswith("Bearer"):
+            tokenstring = authheader.split()[1]
+            try:
+                token = AccessToken.objects.get(token=tokenstring)
+                request.access_token = token
+            except AccessToken.DoesNotExist as e:
+                log.exception(e)
+        response = self.get_response(request)
+        return response


Test patch:
diff --git a/tests/test_auth_backends.py b/tests/test_auth_backends.py
--- a/tests/test_auth_backends.py
+++ b/tests/test_auth_backends.py
@@ -10,7 +10,7 @@
 from django.utils.timezone import now, timedelta
 
 from oauth2_provider.backends import OAuth2Backend
-from oauth2_provider.middleware import OAuth2TokenMiddleware
+from oauth2_provider.middleware import OAuth2ExtraTokenMiddleware, OAuth2TokenMiddleware
 from oauth2_provider.models import get_access_token_model, get_application_model
 
 
@@ -162,3 +162,62 @@ def test_middleware_response_header(self):
         response = m(request)
         self.assertIn("Vary", response)
         self.assertIn("Authorization", response["Vary"])
+
+
+@override_settings(
+    AUTHENTICATION_BACKENDS=(
+        "oauth2_provider.backends.OAuth2Backend",
+        "django.contrib.auth.backends.ModelBackend",
+    ),
+)
+@modify_settings(
+    MIDDLEWARE={
+        "append": "oauth2_provider.middleware.OAuth2TokenMiddleware",
+    }
+)
+class TestOAuth2ExtraTokenMiddleware(BaseTest):
+    def setUp(self):
+        super().setUp()
+        self.anon_user = AnonymousUser()
+
+    def dummy_get_response(self, request):
+        return HttpResponse()
+
+    def test_middleware_wrong_headers(self):
+        m = OAuth2ExtraTokenMiddleware(self.dummy_get_response)
+        request = self.factory.get("/a-resource")
+        m(request)
+        self.assertFalse(hasattr(request, "access_token"))
+        auth_headers = {
+            "HTTP_AUTHORIZATION": "Beerer " + "badstring",  # a Beer token for you!
+        }
+        request = self.factory.get("/a-resource", **auth_headers)
+        m(request)
+        self.assertFalse(hasattr(request, "access_token"))
+
+    def test_middleware_token_does_not_exist(self):
+        m = OAuth2ExtraTokenMiddleware(self.dummy_get_response)
+        auth_headers = {
+            "HTTP_AUTHORIZATION": "Bearer " + "badtokstr",
+        }
+        request = self.factory.get("/a-resource", **auth_headers)
+        m(request)
+        self.assertFalse(hasattr(request, "access_token"))
+
+    def test_middleware_success(self):
+        m = OAuth2ExtraTokenMiddleware(self.dummy_get_response)
+        auth_headers = {
+            "HTTP_AUTHORIZATION": "Bearer " + "tokstr",
+        }
+        request = self.factory.get("/a-resource", **auth_headers)
+        m(request)
+        self.assertEqual(request.access_token, self.token)
+
+    def test_middleware_response(self):
+        m = OAuth2ExtraTokenMiddleware(self.dummy_get_response)
+        auth_headers = {
+            "HTTP_AUTHORIZATION": "Bearer " + "tokstr",
+        }
+        request = self.factory.get("/a-resource", **auth_headers)
+        response = m(request)
+        self.assertIsInstance(response, HttpResponse)