From c888359f3c42bec235b2c5caab2069c9ed62457c Mon Sep 17 00:00:00 2001
From: Jonathan Huot <jonathan.huot@gmail.com>
Date: Fri, 22 May 2026 19:51:42 +0000
Subject: [PATCH] Remove JSONP support from token revocation

JSONP was useful in the past for cross-origin requests but has been
superseded by CORS browser protections. This change removes the outdated
JSONP functionality.

Breaking changes:
- Remove enable_jsonp parameter from RevocationEndpoint
- Remove callback parameter from prepare_token_revocation_request
- Remove JSONP documentation and examples
- Remove JSONP tests

The token revocation endpoint now returns empty response bodies on
success instead of JSONP-wrapped responses.
---
 CHANGELOG.rst                                 |  3 +++
 oauthlib/oauth2/rfc6749/clients/base.py       | 24 ++-----------------
 .../oauth2/rfc6749/endpoints/revocation.py    | 11 ++-------
 oauthlib/oauth2/rfc6749/parameters.py         |  8 ++-----
 tests/oauth2/rfc6749/clients/test_base.py     |  7 ------
 .../endpoints/test_revocation_endpoint.py     | 13 ----------
 6 files changed, 9 insertions(+), 57 deletions(-)

diff --git a/oauthlib/oauth2/rfc6749/clients/base.py b/oauthlib/oauth2/rfc6749/clients/base.py
index 17f833d2..cdbbc191 100644
--- a/oauthlib/oauth2/rfc6749/clients/base.py
+++ b/oauthlib/oauth2/rfc6749/clients/base.py
@@ -320,7 +320,7 @@ def prepare_refresh_token_request(self, token_url, refresh_token=None,
         return token_url, FORM_ENC_HEADERS, body
 
     def prepare_token_revocation_request(self, revocation_url, token,
-                                         token_type_hint="access_token", body='', callback=None, **kwargs):
+                                         token_type_hint="access_token", body='', **kwargs):
         """Prepare a token revocation request.
 
         :param revocation_url: Provider token revocation endpoint URL.
@@ -329,14 +329,9 @@ def prepare_token_revocation_request(self, revocation_url, token,
             ``"refresh_token"``. This is optional and if you wish to not pass it you
             must provide ``token_type_hint=None``.
         :param body:
-        :param callback: A jsonp callback such as ``package.callback`` to be invoked
-            upon receiving the response. Not that it should not include a () suffix.
         :param kwargs: Additional parameters to included in the request.
         :returns: The prepared request tuple with (url, headers, body).
 
-        Note that JSONP request may use GET requests as the parameters will
-        be added to the request URL query as opposed to the request body.
-
         An example of a revocation request
 
         .. code-block:: http
@@ -348,21 +343,6 @@ def prepare_token_revocation_request(self, revocation_url, token,
 
             token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token
 
-        An example of a jsonp revocation request
-
-        .. code-block:: http
-
-            GET /revoke?token=agabcdefddddafdd&callback=package.myCallback HTTP/1.1
-            Host: server.example.com
-            Content-Type: application/x-www-form-urlencoded
-            Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
-
-        and an error response
-
-        .. code-block:: javascript
-
-            package.myCallback({"error":"unsupported_token_type"});
-
         Note that these requests usually require client credentials, client_id in
         the case for public clients and provider specific authentication
         credentials for confidential clients.
@@ -371,7 +351,7 @@ def prepare_token_revocation_request(self, revocation_url, token,
             raise InsecureTransportError()
 
         return prepare_token_revocation_request(revocation_url, token,
-                                                token_type_hint=token_type_hint, body=body, callback=callback,
+                                                token_type_hint=token_type_hint, body=body,
                                                 **kwargs)
 
     def parse_request_body_response(self, body, scope=None, **kwargs):
diff --git a/oauthlib/oauth2/rfc6749/endpoints/revocation.py b/oauthlib/oauth2/rfc6749/endpoints/revocation.py
index 596d0860..06b450a4 100644
--- a/oauthlib/oauth2/rfc6749/endpoints/revocation.py
+++ b/oauthlib/oauth2/rfc6749/endpoints/revocation.py
@@ -27,13 +27,11 @@ class RevocationEndpoint(BaseEndpoint):
     valid_token_types = ('access_token', 'refresh_token')
     valid_request_methods = ('POST',)
 
-    def __init__(self, request_validator, supported_token_types=None,
-            enable_jsonp=False):
+    def __init__(self, request_validator, supported_token_types=None):
         BaseEndpoint.__init__(self)
         self.request_validator = request_validator
         self.supported_token_types = (
             supported_token_types or self.valid_token_types)
-        self.enable_jsonp = enable_jsonp
 
     @catch_errors_and_unavailability
     def create_revocation_response(self, uri, http_method='POST', body=None,
@@ -69,18 +67,13 @@ def create_revocation_response(self, uri, http_method='POST', body=None,
         except OAuth2Error as e:
             log.debug('Client error during validation of %r. %r.', request, e)
             response_body = e.json
-            if self.enable_jsonp and request.callback:
-                response_body = '{}({});'.format(request.callback, response_body)
             resp_headers.update(e.headers)
             return resp_headers, response_body, e.status_code
 
         self.request_validator.revoke_token(request.token,
                                             request.token_type_hint, request)
 
-        response_body = ''
-        if self.enable_jsonp and request.callback:
-            response_body = request.callback + '();'
-        return {}, response_body, 200
+        return {}, '', 200
 
     def validate_revocation_request(self, request):
         """Ensure the request is valid.
diff --git a/oauthlib/oauth2/rfc6749/parameters.py b/oauthlib/oauth2/rfc6749/parameters.py
index 13f33874..1b026037 100644
--- a/oauthlib/oauth2/rfc6749/parameters.py
+++ b/oauthlib/oauth2/rfc6749/parameters.py
@@ -172,7 +172,7 @@ def prepare_token_request(grant_type, body='', include_client_id=True, code_veri
 
 
 def prepare_token_revocation_request(url, token, token_type_hint="access_token",
-        callback=None, body='', **kwargs):
+        body='', **kwargs):
     """Prepare a token revocation request.
 
     The client constructs the request by including the following parameters
@@ -222,11 +222,7 @@ def prepare_token_revocation_request(url, token, token_type_hint="access_token",
 
     headers = {'Content-Type': 'application/x-www-form-urlencoded'}
 
-    if callback:
-        params.append(('callback', callback))
-        return add_params_to_uri(url, params), headers, body
-    else:
-        return url, headers, add_params_to_qs(body, params)
+    return url, headers, add_params_to_qs(body, params)
 
 
 def parse_authorization_code_response(uri, state=None):
diff --git a/tests/oauth2/rfc6749/clients/test_base.py b/tests/oauth2/rfc6749/clients/test_base.py
index e229471c..b80fb0cf 100644
--- a/tests/oauth2/rfc6749/clients/test_base.py
+++ b/tests/oauth2/rfc6749/clients/test_base.py
@@ -237,13 +237,6 @@ def test_revocation_request(self):
         self.assertEqual(h, {'Content-Type': 'application/x-www-form-urlencoded'})
         self.assertEqual(b, 'token=%s&token_type_hint=refresh_token' % token)
 
-        # JSONP
-        u, h, b = client.prepare_token_revocation_request(
-            url, token, callback='hello.world')
-        self.assertURLEqual(u, url + '?callback=hello.world&token=%s&token_type_hint=access_token' % token)
-        self.assertEqual(h, {'Content-Type': 'application/x-www-form-urlencoded'})
-        self.assertEqual(b, '')
-
     def test_prepare_authorization_request(self):
         redirect_url = 'https://example.com/callback/'
         scopes = 'read'
diff --git a/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py b/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py
index 338dbd91..d347b176 100644
--- a/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py
+++ b/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py
@@ -88,19 +88,6 @@ def test_revoke_token_public_client_authentication_failed(self):
         self.assertEqual(loads(b)['error'], 'invalid_client')
         self.assertEqual(s, 401)
 
-    def test_revoke_with_callback(self):
-        endpoint = RevocationEndpoint(self.validator, enable_jsonp=True)
-        callback = 'package.hello_world'
-        for token_type in ('access_token', 'refresh_token', 'invalid'):
-            body = urlencode([('token', 'foo'),
-                              ('token_type_hint', token_type),
-                              ('callback', callback)])
-            h, b, s = endpoint.create_revocation_response(self.uri,
-                    headers=self.headers, body=body)
-            self.assertEqual(h, {})
-            self.assertEqual(b, callback + '();')
-            self.assertEqual(s, 200)
-
     def test_revoke_unsupported_token(self):
         endpoint = RevocationEndpoint(self.validator,
                                       supported_token_types=['access_token'])
