Skip to content

Commit 7becf1c

Browse files
committed
Raise InvalidGrantError if no grant associated with auth code exists
Previously, when invalidating an authorization code after it has been used, if for whatever reason the associated grant object no longer exists, an uncaught exception would be raised - Grant.DoesNotExist. This could be caused by concurrent requests being made using the same authorization token. We now handle this scenario gracefully by catching Grant.DoesNotExist and returning an InvalidGrantError.
1 parent aede24b commit 7becf1c

File tree

4 files changed

+30
-5
lines changed

4 files changed

+30
-5
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,4 @@ pySilver
119119
Wouter Klein Heerenbrink
120120
Yaroslav Halchenko
121121
Yuri Savin
122+
Miriam Forner

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
* Update middleware, validators, and views to use token checksums instead of token for token retrieval and validation.
2525
* #1446 use generic models pk instead of id.
2626
* Bump oauthlib version to 3.2.0 and above
27+
* Update the OAuth2Validator's invalidate_authorization_code method to return an InvalidGrantError if the associated grant does not exist.
2728

2829
### Deprecated
2930
### Removed

oauth2_provider/oauth2_validators.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from jwcrypto import jws, jwt
2525
from jwcrypto.common import JWException
2626
from jwcrypto.jwt import JWTExpired
27-
from oauthlib.oauth2.rfc6749 import utils
27+
from oauthlib.oauth2.rfc6749 import errors, utils
2828
from oauthlib.openid import RequestValidator
2929

3030
from .exceptions import FatalClientError
@@ -318,10 +318,15 @@ def confirm_redirect_uri(self, client_id, code, redirect_uri, client, *args, **k
318318

319319
def invalidate_authorization_code(self, client_id, code, request, *args, **kwargs):
320320
"""
321-
Remove the temporary grant used to swap the authorization token
321+
Remove the temporary grant used to swap the authorization token.
322+
323+
:raises: InvalidGrantError if the grant does not exist.
322324
"""
323-
grant = Grant.objects.get(code=code, application=request.client)
324-
grant.delete()
325+
try:
326+
grant = Grant.objects.get(code=code, application=request.client)
327+
grant.delete()
328+
except Grant.DoesNotExist:
329+
raise errors.InvalidGrantError(request=request)
325330

326331
def validate_client_id(self, client_id, request, *args, **kwargs):
327332
"""

tests/test_oauth2_validators.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@
99
from django.utils import timezone
1010
from jwcrypto import jwt
1111
from oauthlib.common import Request
12+
from oauthlib.oauth2.rfc6749 import errors as rfc6749_errors
1213

1314
from oauth2_provider.exceptions import FatalClientError
14-
from oauth2_provider.models import get_access_token_model, get_application_model, get_refresh_token_model
15+
from oauth2_provider.models import (
16+
get_access_token_model,
17+
get_application_model,
18+
get_grant_model,
19+
get_refresh_token_model,
20+
)
1521
from oauth2_provider.oauth2_backends import get_oauthlib_core
1622
from oauth2_provider.oauth2_validators import OAuth2Validator
1723

@@ -28,6 +34,7 @@
2834
UserModel = get_user_model()
2935
Application = get_application_model()
3036
AccessToken = get_access_token_model()
37+
Grant = get_grant_model()
3138
RefreshToken = get_refresh_token_model()
3239

3340
CLEARTEXT_SECRET = "1234567890abcdefghijklmnopqrstuvwxyz"
@@ -578,3 +585,14 @@ def test_validate_id_token_bad_token_no_aud(oauth2_settings, mocker, oidc_key):
578585
validator = OAuth2Validator()
579586
status = validator.validate_id_token(token.serialize(), ["openid"], mocker.sentinel.request)
580587
assert status is False
588+
589+
590+
@pytest.mark.django_db
591+
def test_invalidate_authorization_token_returns_invalid_grant_error_when_grant_does_not_exist():
592+
client_id = "123"
593+
code = "12345"
594+
request = Request("/")
595+
assert Grant.objects.all().count() == 0
596+
with pytest.raises(rfc6749_errors.InvalidGrantError):
597+
validator = OAuth2Validator()
598+
validator.invalidate_authorization_code(client_id=client_id, code=code, request=request)

0 commit comments

Comments
 (0)