Skip to content

Commit 1623bcf

Browse files
committed
Merge branch 'DEP-368-fix-permanent-refresh-tokens' of https://github.com/waveaccounting/django-oauth-toolkit into waveaccounting-DEP-368-fix-permanent-refresh-tokens
2 parents bc50e0a + 1f85558 commit 1623bcf

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

oauth2_provider/oauth2_validators.py

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

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

339340
def validate_refresh_token(self, refresh_token, client, request, *args, **kwargs):
@@ -344,6 +345,7 @@ def validate_refresh_token(self, refresh_token, client, request, *args, **kwargs
344345
try:
345346
rt = RefreshToken.objects.get(token=refresh_token)
346347
request.user = rt.user
348+
# Temporary store RefreshToken instance to be reused by get_original_scopes.
347349
request.refresh_token = rt
348350
return rt.application == client
349351

oauth2_provider/tests/test_authorization_code.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import base64
44
import json
55
import datetime
6+
import mock
67

78
from django.test import TestCase, RequestFactory
89
from django.core.urlresolvers import reverse
@@ -11,6 +12,7 @@
1112
from ..compat import urlparse, parse_qs, urlencode, get_user_model
1213
from ..models import get_application_model, Grant, AccessToken
1314
from ..settings import oauth2_settings
15+
from ..oauth2_validators import OAuth2Validator
1416
from ..views import ProtectedResourceView
1517

1618
from .test_utils import TestCaseUtils
@@ -495,6 +497,36 @@ def test_refresh_fail_repeating_requests(self):
495497
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
496498
self.assertEqual(response.status_code, 401)
497499

500+
def test_refresh_repeating_requests_non_rotating_tokens(self):
501+
"""
502+
Try refreshing an access token with the same refresh token more than once when not rotating tokens.
503+
"""
504+
self.client.login(username="test_user", password="123456")
505+
authorization_code = self.get_auth()
506+
507+
token_request_data = {
508+
'grant_type': 'authorization_code',
509+
'code': authorization_code,
510+
'redirect_uri': 'http://example.it'
511+
}
512+
auth_headers = self.get_basic_auth_header(self.application.client_id, self.application.client_secret)
513+
514+
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
515+
content = json.loads(response.content.decode("utf-8"))
516+
self.assertTrue('refresh_token' in content)
517+
518+
token_request_data = {
519+
'grant_type': 'refresh_token',
520+
'refresh_token': content['refresh_token'],
521+
'scope': content['scope'],
522+
}
523+
524+
with mock.patch('oauthlib.oauth2.rfc6749.request_validator.RequestValidator.rotate_refresh_token', return_value=False):
525+
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
526+
self.assertEqual(response.status_code, 200)
527+
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
528+
self.assertEqual(response.status_code, 200)
529+
498530
def test_basic_auth_bad_authcode(self):
499531
"""
500532
Request an access token using a bad authorization code

oauth2_provider/tests/test_models.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from django.test.utils import override_settings
1111
from django.core.exceptions import ValidationError
1212

13-
from ..models import AccessToken, get_application_model
13+
from ..models import AccessToken, get_application_model, Grant, AccessToken, RefreshToken
1414
from ..compat import get_user_model
1515

1616

@@ -98,3 +98,24 @@ def test_related_objects(self):
9898
related_object_names = [ro.name for ro in UserModel._meta.get_all_related_objects()]
9999
self.assertNotIn('oauth2_provider:application', related_object_names)
100100
self.assertIn('tests:testapplication', related_object_names)
101+
102+
103+
class TestGrantModel(TestCase):
104+
105+
def test_str(self):
106+
grant = Grant(code="test_code")
107+
self.assertEqual("%s" % grant, grant.code)
108+
109+
110+
class TestAccessTokenModel(TestCase):
111+
112+
def test_str(self):
113+
access_token = AccessToken(token="test_token")
114+
self.assertEqual("%s" % access_token, access_token.token)
115+
116+
117+
class TestRefreshTokenModel(TestCase):
118+
119+
def test_str(self):
120+
refresh_token = RefreshToken(token="test_token")
121+
self.assertEqual("%s" % refresh_token, refresh_token.token)

0 commit comments

Comments
 (0)