Skip to content

Commit 231d4b0

Browse files
Merge pull request #204 from mizvyt/master
Set Django request object through a server method call
2 parents d13da37 + a5b7203 commit 231d4b0

File tree

2 files changed

+52
-10
lines changed

2 files changed

+52
-10
lines changed

rest_framework_social_oauth2/oauth2_backends.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,33 @@
55
from oauth2_provider.oauth2_backends import OAuthLibCore
66
from oauth2_provider.settings import oauth2_settings
77

8+
from .oauth2_endpoints import SocialTokenServer
9+
810

911
class KeepRequestCore(oauth2_settings.OAUTH2_BACKEND_CLASS):
1012
"""
11-
Subclass of OAuthLibCore used only for the sake of keeping the django
12-
request object by placing it in the headers.
13-
This is a hack and we need a better solution for this.
13+
Subclass of `oauth2_settings.OAUTH2_BACKEND_CLASS`, used for the sake of
14+
keeping the Django request object by passing it through to the
15+
`server_class` instance.
16+
17+
This backend should only be used in views with SocialTokenServer
18+
as the `server_class`.
1419
"""
15-
def _extract_params(self, request):
16-
uri, http_method, body, headers = super(KeepRequestCore, self)._extract_params(request)
17-
headers["Django-request-object"] = request
18-
return uri, http_method, body, headers
20+
21+
def __init__(self, *args, **kwargs):
22+
super(KeepRequestCore, self).__init__(*args, **kwargs)
23+
if not isinstance(self.server, SocialTokenServer):
24+
raise TypeError(
25+
"server_class must be an instance of 'SocialTokenServer'"
26+
)
27+
28+
def create_token_response(self, request):
29+
"""
30+
A wrapper method that calls create_token_response on `server_class` instance.
31+
This method is modified to also pass the `django.http.HttpRequest`
32+
request object.
33+
34+
:param request: The current django.http.HttpRequest object
35+
"""
36+
self.server.set_request_object(request)
37+
return super(KeepRequestCore, self).create_token_response(request)

rest_framework_social_oauth2/oauth2_endpoints.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import logging
66

7+
from django.http import HttpRequest
8+
79
from oauthlib.common import Request
810
from oauthlib.oauth2.rfc6749.endpoints.token import TokenEndpoint
911
from oauthlib.oauth2.rfc6749.tokens import BearerToken
@@ -15,8 +17,10 @@
1517

1618

1719
class SocialTokenServer(TokenEndpoint):
20+
"""An endpoint used only for token generation.
1821
19-
"""An endpoint used only for token generation."""
22+
Use this with the KeepRequestCore backend class.
23+
"""
2024

2125
def __init__(self, request_validator, token_generator=None,
2226
token_expires_in=None, refresh_token_generator=None, **kwargs):
@@ -32,6 +36,7 @@ def __init__(self, request_validator, token_generator=None,
3236
:param kwargs: Extra parameters to pass to authorization-,
3337
token-, resource-, and revocation-endpoint constructors.
3438
"""
39+
self._params = {}
3540
refresh_grant = SocialTokenGrant(request_validator)
3641
bearer = BearerToken(request_validator, token_generator,
3742
token_expires_in, refresh_token_generator)
@@ -41,17 +46,35 @@ def __init__(self, request_validator, token_generator=None,
4146
},
4247
default_token_type=bearer)
4348

49+
def set_request_object(self, request):
50+
"""This should be called by the KeepRequestCore backend class before
51+
calling `create_token_response` to store the Django request object.
52+
"""
53+
if not isinstance(request, HttpRequest):
54+
raise TypeError(
55+
"request must be an instance of 'django.http.HttpRequest'"
56+
)
57+
self._params['http_request'] = request
58+
59+
def pop_request_object(self):
60+
"""This is called internaly by `create_token_response`
61+
to fetch the Django request object and cleanup class instance.
62+
"""
63+
return self._params.pop('http_request', None)
64+
4465
# We override this method just so we can pass the django request object
4566
@catch_errors_and_unavailability
4667
def create_token_response(self, uri, http_method='GET', body=None,
4768
headers=None, credentials=None):
4869
"""Extract grant_type and route to the designated handler."""
49-
django_request = headers.pop("Django-request-object", None)
5070
request = Request(
5171
uri, http_method=http_method, body=body, headers=headers)
5272
request.scopes = None
5373
request.extra_credentials = credentials
54-
request.django_request = django_request
74+
75+
# Make sure we consume the django request object
76+
request.django_request = self.pop_request_object()
77+
5578
grant_type_handler = self.grant_types.get(request.grant_type,
5679
self.default_grant_type_handler)
5780
log.debug('Dispatching grant_type %s request to %r.',

0 commit comments

Comments
 (0)