Fix fetching old access_token from refresh_token #810
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Issue
When I scale my back-end to have multiple django instances running to help with growing server demand I sometime receive the following stacktrace error:
This is due to multiple refresh_token requests being sent from the same client to
/api/oauth2/token/where the requests are handled in parallel by the back-end.oauthlibtries to validate the refresh tokenhttps://github.com/oauthlib/oauthlib/blob/b71636e85f845b79b5a56de6480fcba9d1415720/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py#L58
which then calls the
validate_refresh_tokenindjago-oauth-toolkithttps://github.com/oauthlib/oauthlib/blob/b71636e85f845b79b5a56de6480fcba9d1415720/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py#L115-L116
The
refresh_tokenis read from the database and attached to therequestobjecthttps://github.com/jazzband/django-oauth-toolkit/blob/eb381c30affa60a0465a8a2f2c5ca0890ece5362/oauth2_provider/oauth2_validators.py#L637-L642
It then calls
get_original_scopeshttps://github.com/oauthlib/oauthlib/blob/b71636e85f845b79b5a56de6480fcba9d1415720/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py#L122-L123
which in
django-oauth-toolkitreads theaccess_tokenfrom therefresh_tokenthis requires a db lookuphttps://github.com/jazzband/django-oauth-toolkit/blob/eb381c30affa60a0465a8a2f2c5ca0890ece5362/oauth2_provider/oauth2_validators.py#L624
later
oauthlibsaves the tokenhttps://github.com/oauthlib/oauthlib/blob/b71636e85f845b79b5a56de6480fcba9d1415720/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py#L70
which eventually calls
save_bearer_tokenhttps://github.com/oauthlib/oauthlib/blob/b71636e85f845b79b5a56de6480fcba9d1415720/oauthlib/oauth2/rfc6749/request_validator.py#L315
and then
revoke()therefresh_tokenhttps://github.com/jazzband/django-oauth-toolkit/blob/eb381c30affa60a0465a8a2f2c5ca0890ece5362/oauth2_provider/oauth2_validators.py#L532
which in tern deletes the access token.
If you have two servers you can have
Server 1: (1) -> (2) -> (3) -> (4)
Server 2: (1) -> (2) ---------------> (3) -> (4)
Notice server 2 only gets to check the
refresh_tokenafter server 1 has already revoked (deleted) theaccess_tokenthat is attached to therefresh_tokencausing the error on server 2 (stack-trace) above.Description of the Change
Ensure that a database lookup is not required to get the
access_tokenfrom therefresh_tokenin case another parallel refresh request has already removed thataccess_tokenfrom the database