Skip to content

Commit ee7e0af

Browse files
committed
Support for OAuth2 sessions revocation
Add support for revocation in OAuth2 sessions Signed-off-by: Louis Rannou <[email protected]>
1 parent 3a2a852 commit ee7e0af

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

requests_oauthlib/oauth2_session.py

+87
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from oauthlib.oauth2 import WebApplicationClient, InsecureTransportError
77
from oauthlib.oauth2 import LegacyApplicationClient
88
from oauthlib.oauth2 import TokenExpiredError, is_secure_transport
9+
from oauthlib.oauth2 import UnsupportedTokenTypeError
10+
from oauthlib.oauth2 import TemporarilyUnavailableError, ServerError
911
import requests
1012

1113
log = logging.getLogger(__name__)
@@ -94,8 +96,10 @@ def __init__(
9496
self.compliance_hook = {
9597
"access_token_response": set(),
9698
"refresh_token_response": set(),
99+
"revoke_token_response": set(),
97100
"protected_request": set(),
98101
"refresh_token_request": set(),
102+
"revoke_token_request": set(),
99103
"access_token_request": set(),
100104
}
101105

@@ -481,6 +485,87 @@ def refresh_token(
481485
self.token["refresh_token"] = refresh_token
482486
return self.token
483487

488+
def revoke_token(
489+
self,
490+
token_url,
491+
token=None,
492+
token_type=None,
493+
body="",
494+
auth=None,
495+
timeout=None,
496+
headers=None,
497+
verify=None,
498+
proxies=None,
499+
**kwargs
500+
):
501+
"""Revoke a token pair using a token.
502+
503+
:param token_url: The token endpoint, must be HTTPS.
504+
:param token: The token to revoke.
505+
:param token_type: The type of token to revoke.
506+
:param body: Optional application/x-www-form-urlencoded body to add the
507+
include in the token request. Prefer kwargs over body.
508+
:param auth: An auth tuple or method as accepted by `requests`.
509+
:param timeout: Timeout of the request in seconds.
510+
:param headers: A dict of headers to be used by `requests`.
511+
:param verify: Verify SSL certificate.
512+
:param proxies: The `proxies` argument will be passed to `requests`.
513+
:param kwargs: Extra parameters to include in the token request.
514+
:return: A token dict
515+
"""
516+
if not token_url:
517+
raise ValueError("No token endpoint set for revoke.")
518+
519+
if not is_secure_transport(token_url):
520+
raise InsecureTransportError()
521+
522+
token = token or self.token.get("token")
523+
token_type = token_type or self.token.get("token_type")
524+
525+
if token_type:
526+
(url, _headers, _body) = self._client.prepare_token_revocation_request(
527+
token_url, token, token_type, body=body, scope=self.scope, **kwargs)
528+
else:
529+
(url, _headers, _body) = self._client.prepare_revocation_request(
530+
token_url, token, body=body, scope=self.scope, **kwargs)
531+
log.debug("Prepared revocation request %s", body)
532+
533+
if headers is not None:
534+
_headers = headers
535+
if body is not None:
536+
_body = body
537+
538+
for hook in self.compliance_hook["revoke_token_request"]:
539+
log.debug("Invoking revoke_token_request hook %s.", hook)
540+
url, _headers, _body = hook(url, _headers, _body)
541+
542+
r = self.post(
543+
url,
544+
data=dict(urldecode(_body)),
545+
auth=auth,
546+
timeout=timeout,
547+
headers=_headers,
548+
verify=verify,
549+
withhold_token=True,
550+
proxies=proxies,
551+
)
552+
log.debug("Request to revoke token completed with status %s.", r.status_code)
553+
log.debug("Response headers were %s and content %s.", r.headers, r.text)
554+
log.debug(
555+
"Invoking %d token response hooks.",
556+
len(self.compliance_hook["revoke_token_response"]),
557+
)
558+
for hook in self.compliance_hook["revoke_token_response"]:
559+
log.debug("Invoking hook %s.", hook)
560+
r = hook(r)
561+
562+
if not r.ok and r.status_code == 400:
563+
if 'unsupported_token_type' in r.text:
564+
raise UnsupportedTokenTypeError("Revocation not supported by server")
565+
raise ServerError('Server error')
566+
elif r.code == 503:
567+
raise TemporarilyUnavailableError("Service unavailable")
568+
484569
def request(
485570
self,
486571
method,
@@ -555,9 +640,11 @@ def register_compliance_hook(self, hook_type, hook):
555640
Available hooks are:
556641
access_token_response invoked before token parsing.
557642
refresh_token_response invoked before refresh token parsing.
643+
revoke_token_response invoked after token revocation.
558644
protected_request invoked before making a request.
559645
access_token_request invoked before making a token fetch request.
560646
refresh_token_request invoked before making a refresh request.
647+
revoke_token_request invoked before making a revoke request.
561648
562649
If you find a new hook is needed please send a GitHub PR request
563650
or open an issue.

0 commit comments

Comments
 (0)