diff --git a/AUTHORS.rst b/AUTHORS.rst index b9391af7..c8fba5e9 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -22,3 +22,4 @@ Patches and Suggestions - Vinay Raikar - kracekumar - David Baumgold +- Craig Anderson diff --git a/requests_oauthlib/compliance_fixes/__init__.py b/requests_oauthlib/compliance_fixes/__init__.py index 8d3aba1c..0e8e3ac8 100644 --- a/requests_oauthlib/compliance_fixes/__init__.py +++ b/requests_oauthlib/compliance_fixes/__init__.py @@ -7,3 +7,4 @@ from .mailchimp import mailchimp_compliance_fix from .weibo import weibo_compliance_fix from .plentymarkets import plentymarkets_compliance_fix +from .ebay import ebay_compliance_fix diff --git a/requests_oauthlib/compliance_fixes/ebay.py b/requests_oauthlib/compliance_fixes/ebay.py new file mode 100644 index 00000000..4aa423b3 --- /dev/null +++ b/requests_oauthlib/compliance_fixes/ebay.py @@ -0,0 +1,23 @@ +import json +from oauthlib.common import to_unicode + + +def ebay_compliance_fix(session): + def _compliance_fix(response): + token = json.loads(response.text) + + # eBay responds with non-compliant token types. + # https://developer.ebay.com/api-docs/static/oauth-client-credentials-grant.html + # https://developer.ebay.com/api-docs/static/oauth-auth-code-grant-request.html + # Modify these to be "Bearer". + if token.get("token_type") in ["Application Access Token", "User Access Token"]: + token["token_type"] = "Bearer" + fixed_token = json.dumps(token) + response._content = to_unicode(fixed_token).encode("utf-8") + + return response + + session.register_compliance_hook("access_token_response", _compliance_fix) + session.register_compliance_hook("refresh_token_response", _compliance_fix) + + return session diff --git a/requests_oauthlib/oauth2_session.py b/requests_oauthlib/oauth2_session.py index bfec8e8d..db446808 100644 --- a/requests_oauthlib/oauth2_session.py +++ b/requests_oauthlib/oauth2_session.py @@ -230,9 +230,9 @@ def fetch_token( `auth` tuple. If the value is `None`, it will be omitted from the request, however if the value is an empty string, an empty string will be sent. - :param cert: Client certificate to send for OAuth 2.0 Mutual-TLS Client - Authentication (draft-ietf-oauth-mtls). Can either be the - path of a file containing the private key and certificate or + :param cert: Client certificate to send for OAuth 2.0 Mutual-TLS Client + Authentication (draft-ietf-oauth-mtls). Can either be the + path of a file containing the private key and certificate or a tuple of two filenames for certificate and key. :param kwargs: Extra parameters to include in the token request. :return: A token dict diff --git a/tests/test_compliance_fixes.py b/tests/test_compliance_fixes.py index e03ec3e5..5c90d526 100644 --- a/tests/test_compliance_fixes.py +++ b/tests/test_compliance_fixes.py @@ -19,6 +19,7 @@ from requests_oauthlib.compliance_fixes import slack_compliance_fix 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 class FacebookComplianceFixTest(TestCase): @@ -305,3 +306,29 @@ def test_fetch_access_token(self): "refresh_token": "iG2kBGIjcXaRE4xmTVUnv7xwxX7XMcWCHqJmFaSX", }, ) + + +class EbayComplianceFixTest(TestCase): + def setUp(self): + mocker = requests_mock.Mocker() + mocker.post( + "https://api.ebay.com/identity/v1/oauth2/token", + json={ + "access_token": "this is the access token", + "expires_in": 7200, + "token_type": "Application Access Token", + }, + headers={"Content-Type": "application/json"}, + ) + mocker.start() + self.addCleanup(mocker.stop) + + session = OAuth2Session() + self.fixed_session = ebay_compliance_fix(session) + + def test_fetch_access_token(self): + token = self.fixed_session.fetch_token( + "https://api.ebay.com/identity/v1/oauth2/token", + authorization_response="https://i.b/?code=hello", + ) + assert token["token_type"] == "Bearer"