Skip to content

Commit ff7cccf

Browse files
committed
Restoring request.refresh_token at get_original_scopes.
1 parent 7f76679 commit ff7cccf

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

oauth2_provider/oauth2_validators.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,9 +332,10 @@ def validate_user(self, username, password, client, request, *args, **kwargs):
332332
return False
333333

334334
def get_original_scopes(self, refresh_token, request, *args, **kwargs):
335-
# TODO: since this method is invoked *after* validate_refresh_token, could we avoid this
336-
# second query for RefreshToken?
337-
rt = RefreshToken.objects.get(token=refresh_token)
335+
# Avoid second query for RefreshToken since this method is invoked *after* validate_refresh_token.
336+
rt = request.refresh_token
337+
# Restore request.refresh_token
338+
request.refresh_token = rt.token
338339
return rt.access_token.scope
339340

340341
def validate_refresh_token(self, refresh_token, client, request, *args, **kwargs):
@@ -345,6 +346,8 @@ def validate_refresh_token(self, refresh_token, client, request, *args, **kwargs
345346
try:
346347
rt = RefreshToken.objects.get(token=refresh_token)
347348
request.user = rt.user
349+
# Temporary store RefreshToken instance to be reused by self.get_original_scopes.
350+
request.refresh_token = rt
348351
return rt.application == client
349352

350353
except RefreshToken.DoesNotExist:

oauth2_provider/tests/test_authorization_code.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from ..compat import urlparse, parse_qs, urlencode, get_user_model
1212
from ..models import get_application_model, Grant, AccessToken
1313
from ..settings import oauth2_settings
14+
from ..oauth2_validators import OAuth2Validator
1415
from ..views import ProtectedResourceView
1516

1617
from .test_utils import TestCaseUtils
@@ -474,6 +475,43 @@ def test_refresh_fail_repeating_requests(self):
474475
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
475476
self.assertEqual(response.status_code, 401)
476477

478+
def test_refresh_repeating_requests_non_rotating_tokens(self):
479+
"""
480+
Try refreshing an access token with the same refresh token more than once when not rotating tokens.
481+
"""
482+
class NonRotatingOAuth2Validator(OAuth2Validator):
483+
def rotate_refresh_token(self, request):
484+
return False
485+
validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS
486+
oauth2_settings.OAUTH2_VALIDATOR_CLASS = NonRotatingOAuth2Validator
487+
488+
self.client.login(username="test_user", password="123456")
489+
authorization_code = self.get_auth()
490+
491+
token_request_data = {
492+
'grant_type': 'authorization_code',
493+
'code': authorization_code,
494+
'redirect_uri': 'http://example.it'
495+
}
496+
auth_headers = self.get_basic_auth_header(self.application.client_id, self.application.client_secret)
497+
498+
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
499+
content = json.loads(response.content.decode("utf-8"))
500+
self.assertTrue('refresh_token' in content)
501+
502+
token_request_data = {
503+
'grant_type': 'refresh_token',
504+
'refresh_token': content['refresh_token'],
505+
'scope': content['scope'],
506+
}
507+
508+
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
509+
self.assertEqual(response.status_code, 200)
510+
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
511+
self.assertEqual(response.status_code, 200)
512+
513+
oauth2_settings.OAUTH2_VALIDATOR_CLASS = validator_class
514+
477515
def test_basic_auth_bad_authcode(self):
478516
"""
479517
Request an access token using a bad authorization code

0 commit comments

Comments
 (0)