Skip to content

Commit be34163

Browse files
authored
handle oauthlib errors on create token requests (#1210)
Co-authored-by: andrej <[email protected]>
1 parent da459a1 commit be34163

File tree

4 files changed

+104
-7
lines changed

4 files changed

+104
-7
lines changed

‎AUTHORS‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Aleksander Vaskevich
1616
Alessandro De Angelis
1717
Alex Szabó
1818
Allisson Azevedo
19+
Andrej Zbín
1920
Andrew Chen Wang
2021
Anvesh Agarwal
2122
Aristóbulo Meneses

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2727

2828
### Fixed
2929
* Remove upper version bound on Django, to allow upgrading to Django 4.1.1 bugfix release.
30+
* Handle oauthlib errors on create token requests
3031

3132
## [2.1.0] 2022-06-19
3233

‎oauth2_provider/oauth2_backends.py‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,14 @@ def create_token_response(self, request):
152152
uri, http_method, body, headers=self._extract_params(request)
153153
extra_credentials=self._get_extra_credentials(request)
154154

155-
headers, body, status=self.server.create_token_response(
156-
uri, http_method, body, headers, extra_credentials
157-
)
158-
uri=headers.get("Location", None)
159-
160-
returnuri, headers, body, status
155+
try:
156+
headers, body, status=self.server.create_token_response(
157+
uri, http_method, body, headers, extra_credentials
158+
)
159+
uri=headers.get("Location", None)
160+
returnuri, headers, body, status
161+
exceptOAuth2Errorasexc:
162+
returnNone, exc.headers, exc.json, exc.status_code
161163

162164
defcreate_revocation_response(self, request):
163165
"""

‎tests/test_oauth2_backends.py‎

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
importbase64
12
importjson
23

34
importpytest
5+
fromdjango.contrib.authimportget_user_model
46
fromdjango.testimportRequestFactory, TestCase
7+
fromdjango.utils.timezoneimportnow, timedelta
58

69
fromoauth2_provider.backendsimportget_oauthlib_core
7-
fromoauth2_provider.modelsimportredirect_to_uri_allowed
10+
fromoauth2_provider.modelsimportget_access_token_model, get_application_model, redirect_to_uri_allowed
811
fromoauth2_provider.oauth2_backendsimportJSONOAuthLibCore, OAuthLibCore
912

1013

@@ -50,6 +53,96 @@ def test_application_json_extract_params(self):
5053
self.assertNotIn("password=123456", body)
5154

5255

56+
UserModel=get_user_model()
57+
ApplicationModel=get_application_model()
58+
AccessTokenModel=get_access_token_model()
59+
60+
61+
@pytest.mark.usefixtures("oauth2_settings")
62+
classTestOAuthLibCoreBackendErrorHandling(TestCase):
63+
defsetUp(self):
64+
self.factory=RequestFactory()
65+
self.oauthlib_core=OAuthLibCore()
66+
self.user=UserModel.objects.create_user("john", "[email protected]", "123456")
67+
self.app=ApplicationModel.objects.create(
68+
name="app",
69+
client_id="app_id",
70+
client_secret="app_secret",
71+
client_type=ApplicationModel.CLIENT_CONFIDENTIAL,
72+
authorization_grant_type=ApplicationModel.GRANT_PASSWORD,
73+
user=self.user,
74+
)
75+
76+
deftearDown(self):
77+
self.user.delete()
78+
self.app.delete()
79+
80+
deftest_create_token_response_valid(self):
81+
payload= (
82+
"grant_type=password&username=john&password=123456&client_id=app_id&client_secret=app_secret"
83+
)
84+
request=self.factory.post(
85+
"/o/token/",
86+
payload,
87+
content_type="application/x-www-form-urlencoded",
88+
HTTP_AUTHORIZATION="Basic %s"%base64.b64encode(b"john:123456").decode(),
89+
)
90+
91+
uri, headers, body, status=self.oauthlib_core.create_token_response(request)
92+
self.assertEqual(status, 200)
93+
94+
deftest_create_token_response_query_params(self):
95+
payload= (
96+
"grant_type=password&username=john&password=123456&client_id=app_id&client_secret=app_secret"
97+
)
98+
request=self.factory.post(
99+
"/o/token/?test=foo",
100+
payload,
101+
content_type="application/x-www-form-urlencoded",
102+
HTTP_AUTHORIZATION="Basic %s"%base64.b64encode(b"john:123456").decode(),
103+
)
104+
uri, headers, body, status=self.oauthlib_core.create_token_response(request)
105+
106+
self.assertEqual(status, 400)
107+
self.assertDictEqual(
108+
json.loads(body),
109+
{"error": "invalid_request", "error_description": "URL query parameters are not allowed"},
110+
)
111+
112+
deftest_create_revocation_response_valid(self):
113+
AccessTokenModel.objects.create(
114+
user=self.user, token="tokstr", application=self.app, expires=now() +timedelta(days=365)
115+
)
116+
payload="client_id=app_id&client_secret=app_secret&token=tokstr"
117+
request=self.factory.post(
118+
"/o/revoke_token/",
119+
payload,
120+
content_type="application/x-www-form-urlencoded",
121+
HTTP_AUTHORIZATION="Basic %s"%base64.b64encode(b"john:123456").decode(),
122+
)
123+
uri, headers, body, status=self.oauthlib_core.create_revocation_response(request)
124+
self.assertEqual(status, 200)
125+
126+
deftest_create_revocation_response_query_params(self):
127+
token=AccessTokenModel.objects.create(
128+
user=self.user, token="tokstr", application=self.app, expires=now() +timedelta(days=365)
129+
)
130+
payload="client_id=app_id&client_secret=app_secret&token=tokstr"
131+
request=self.factory.post(
132+
"/o/revoke_token/?test=foo",
133+
payload,
134+
content_type="application/x-www-form-urlencoded",
135+
HTTP_AUTHORIZATION="Basic %s"%base64.b64encode(b"john:123456").decode(),
136+
)
137+
uri, headers, body, status=self.oauthlib_core.create_revocation_response(request)
138+
self.assertEqual(status, 400)
139+
self.assertDictEqual(
140+
json.loads(body),
141+
{"error": "invalid_request", "error_description": "URL query parameters are not allowed"},
142+
)
143+
token.delete()
144+
145+
53146
classTestCustomOAuthLibCoreBackend(TestCase):
54147
"""
55148
Tests that the public API behaves as expected when we override

0 commit comments

Comments
(0)