Skip to content

Commit 854204b

Browse files
authored
Fix access token 500 (#1337)
* try/except when looking for an access token to avoid 500 * try/except when looking for an access token to avoid 500 * adding additionnal tests * adding a test for using a deleted token * returning an empty array, updating tests * updating CHANGELOG and AUTHORS
1 parent 9b91d79 commit 854204b

File tree

4 files changed

+39
-2
lines changed

4 files changed

+39
-2
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Antoine Laurent
2626
Anvesh Agarwal
2727
Aristóbulo Meneses
2828
Aryan Iyappan
29+
Asaf Klibansky
2930
Ash Christopher
3031
Asif Saif Uddin
3132
Bart Merenda

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424
* #1273 Add caching of loading of OIDC private key.
2525
* #1285 Add post_logout_redirect_uris field in application views.
2626
* #1311 Add option to disable client_secret hashing to allow verifying JWTs' signatures.
27+
* #1337 Gracefully handle expired or deleted refresh tokens, in `validate_user`.
2728

2829
- ### Fixed
2930
* #1322 Instructions in documentation on how to create a code challenge and code verifier

oauth2_provider/oauth2_validators.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -725,8 +725,10 @@ def get_original_scopes(self, refresh_token, request, *args, **kwargs):
725725
# validate_refresh_token.
726726
rt = request.refresh_token_instance
727727
if not rt.access_token_id:
728-
return AccessToken.objects.get(source_refresh_token_id=rt.id).scope
729-
728+
try:
729+
return AccessToken.objects.get(source_refresh_token_id=rt.id).scope
730+
except AccessToken.DoesNotExist:
731+
return []
730732
return rt.access_token.scope
731733

732734
def validate_refresh_token(self, refresh_token, client, request, *args, **kwargs):

tests/test_authorization_code.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,39 @@ def test_refresh_repeating_requests_non_rotating_tokens(self):
10021002
response = self.client.post(reverse("oauth2_provider:token"), data=token_request_data, **auth_headers)
10031003
self.assertEqual(response.status_code, 200)
10041004

1005+
def test_refresh_with_deleted_token(self):
1006+
"""
1007+
Ensure that using a deleted refresh token returns 400
1008+
"""
1009+
self.client.login(username="test_user", password="123456")
1010+
authorization_code = self.get_auth()
1011+
1012+
token_request_data = {
1013+
"grant_type": "authorization_code",
1014+
"scope": "read write",
1015+
"code": authorization_code,
1016+
"redirect_uri": "http://example.org",
1017+
}
1018+
auth_headers = get_basic_auth_header(self.application.client_id, CLEARTEXT_SECRET)
1019+
1020+
# get a refresh token
1021+
response = self.client.post(reverse("oauth2_provider:token"), data=token_request_data, **auth_headers)
1022+
1023+
content = json.loads(response.content.decode("utf-8"))
1024+
rt = content["refresh_token"]
1025+
1026+
token_request_data = {
1027+
"grant_type": "refresh_token",
1028+
"refresh_token": rt,
1029+
"scope": "read write",
1030+
}
1031+
1032+
# delete the access token
1033+
AccessToken.objects.filter(token=content["access_token"]).delete()
1034+
1035+
response = self.client.post(reverse("oauth2_provider:token"), data=token_request_data, **auth_headers)
1036+
self.assertEqual(response.status_code, 400)
1037+
10051038
def test_basic_auth_bad_authcode(self):
10061039
"""
10071040
Request an access token using a bad authorization code

0 commit comments

Comments
 (0)