Skip to content

Commit

Permalink
Support non-x-www-form-urlencoded bodies returned from refresh_token_…
Browse files Browse the repository at this point in the history
…request

compliance hook

* Handle the case where a non-x-www-form-urlencoded string is returned
from the refresh_token_request compliance hook, and allow it to be
used as a raw string in the subsequent request
* Add wix compliance fix to send token request and refresh requests
with JSON bodies
* Add unit tests for wix compliance fixes
  • Loading branch information
skray committed Apr 19, 2024
1 parent 45eca1a commit 4241af8
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 1 deletion.
36 changes: 36 additions & 0 deletions requests_oauthlib/compliance_fixes/wix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import json
from oauthlib.common import urldecode

"""
Wix requires the request body for token requests to be sent in JSON format
instead of x-www-form-urlencoded.
"""
def wix_compliance_fix(session):

def _non_compliant_access_token_request_body(
url: str, headers: dict, request_kwargs: dict
):
"""
Move the request body from the `data` kwarg to the `json` kwarg,
and set the `Content-Type` header to `application/json`.
"""
headers["Content-Type"] = "application/json"
request_kwargs["json"] = request_kwargs["data"]
del request_kwargs["data"]
return url, headers, request_kwargs

def _non_compliant_refresh_token_request_body(
token_url: str, headers: dict, body: str
):
"""
Convert the body from a urlencoded string to a JSON string,
and set the `Content-Type` header to `application/json`.
"""
headers["Content-Type"] = "application/json"
body = json.dumps(dict(urldecode(body)))
return token_url, headers, body

session.register_compliance_hook("access_token_request", _non_compliant_access_token_request_body)
session.register_compliance_hook("refresh_token_request", _non_compliant_refresh_token_request_body)

return session
8 changes: 7 additions & 1 deletion requests_oauthlib/oauth2_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,9 +473,15 @@ def refresh_token(
log.debug("Invoking refresh_token_request hook %s.", hook)
token_url, headers, body = hook(token_url, headers, body)

try:
body = dict(urldecode(body))
except ValueError:
log.debug("Could not decode body as urlencoded data. Using body in request as is: %s", body)
pass

r = self.post(
token_url,
data=dict(urldecode(body)),
data=body,
auth=auth,
timeout=timeout,
headers=headers,
Expand Down
44 changes: 44 additions & 0 deletions tests/test_compliance_fixes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from requests_oauthlib.compliance_fixes import instagram_compliance_fix
from requests_oauthlib.compliance_fixes import plentymarkets_compliance_fix
from requests_oauthlib.compliance_fixes import ebay_compliance_fix
from requests_oauthlib.compliance_fixes.wix import wix_compliance_fix


class FacebookComplianceFixTest(TestCase):
Expand Down Expand Up @@ -385,3 +386,46 @@ def test_refresh_token(self):
"https://example.com/refresh",
)
assert token["token_type"] == "Bearer"


class WixComplianceFixTest(TestCase):

def setUp(self):
wix = OAuth2Session()
self.session = wix_compliance_fix(wix)

def test_access_token_request_sent_as_json(self):
mocker = requests_mock.Mocker()
mocker.post(
"https://www.wixapis.com/oauth/access",
request_headers={"Content-Type": "application/json"},
json={"access_token": "sample_access_token", "refresh_token": "sample_refresh_token"},
additional_matcher=lambda req: req.json() == {'grant_type': 'authorization_code', 'code': 'sample_code'}
)
mocker.start()
self.addCleanup(mocker.stop)

token = self.session.fetch_token(
"https://www.wixapis.com/oauth/access",
code="sample_code"
)

self.assertEqual(token, {"access_token": "sample_access_token", "refresh_token": "sample_refresh_token"})

def test_refresh_token_request_sent_as_json(self):
mocker = requests_mock.Mocker()
mocker.post(
"https://www.wixapis.com/oauth/access",
request_headers={"Content-Type": "application/json"},
json={"access_token": "sample_access_token", "refresh_token": "sample_refresh_token"},
additional_matcher=lambda req: req.json() == {'grant_type': 'refresh_token', 'refresh_token': 'sample_refresh_token'}
)
mocker.start()
self.addCleanup(mocker.stop)

token = self.session.refresh_token(
"https://www.wixapis.com/oauth/access",
refresh_token="sample_refresh_token"
)

self.assertEqual(token, {"access_token": "sample_access_token", "refresh_token": "sample_refresh_token"})

0 comments on commit 4241af8

Please sign in to comment.