Skip to content

Commit 0c85536

Browse files
author
Massimiliano Pippi
committed
refresh token handling, fixes #65
1 parent 16c6709 commit 0c85536

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

oauth2_provider/oauth2_validators.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,13 @@ def save_bearer_token(self, token, request, *args, **kwargs):
205205
"""
206206
Save access and refresh token, If refresh token is issued, remove old refresh tokens as in rfc:`6`
207207
"""
208+
if request.refresh_token:
209+
# remove used refresh token
210+
try:
211+
RefreshToken.objects.get(token=request.refresh_token).delete()
212+
except RefreshToken.DoesNotExist:
213+
assert() # TODO though being here would be very strange, at least log the error
214+
208215
expires = timezone.now() + timedelta(seconds=oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS)
209216
if request.grant_type == 'client_credentials':
210217
request.user = request.client.user
@@ -218,9 +225,6 @@ def save_bearer_token(self, token, request, *args, **kwargs):
218225
access_token.save()
219226

220227
if 'refresh_token' in token:
221-
# discard old refresh tokens
222-
RefreshToken.objects.filter(user=request.user).filter(application=request.client).delete()
223-
224228
refresh_token = RefreshToken(
225229
user=request.user,
226230
token=token['refresh_token'],
@@ -255,6 +259,7 @@ def validate_refresh_token(self, refresh_token, client, request, *args, **kwargs
255259
try:
256260
rt = RefreshToken.objects.get(token=refresh_token)
257261
request.user = rt.user
262+
request.refresh_token = rt
258263
return rt.application == client
259264

260265
except RefreshToken.DoesNotExist:

oauth2_provider/tests/test_authorization_code.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,15 @@ def test_refresh(self):
277277
content = json.loads(response.content.decode("utf-8"))
278278
self.assertTrue('refresh_token' in content)
279279

280+
# make a second token request to be sure the previous refresh token remains valid, see #65
281+
authorization_code = self.get_auth()
282+
token_request_data = {
283+
'grant_type': 'authorization_code',
284+
'code': authorization_code,
285+
'redirect_uri': 'http://example.it'
286+
}
287+
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
288+
280289
token_request_data = {
281290
'grant_type': 'refresh_token',
282291
'refresh_token': content['refresh_token'],
@@ -288,6 +297,12 @@ def test_refresh(self):
288297
content = json.loads(response.content.decode("utf-8"))
289298
self.assertTrue('access_token' in content)
290299

300+
# check refresh token cannot be used twice
301+
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
302+
self.assertEqual(response.status_code, 400)
303+
content = json.loads(response.content.decode("utf-8"))
304+
self.assertTrue('invalid_grant' in content.values())
305+
291306
def test_refresh_no_scopes(self):
292307
"""
293308
Request an access token using a refresh token without passing any scope

0 commit comments

Comments
 (0)