diff options
author | robot-piglet <[email protected]> | 2024-03-25 09:11:17 +0300 |
---|---|---|
committer | robot-piglet <[email protected]> | 2024-03-25 09:17:48 +0300 |
commit | 4624e4cfd95649270db02616edde8d0ca249b63d (patch) | |
tree | 1c8a43f50533ca759d137f258e42862e8cf5e80f /contrib/python/requests-oauthlib/requests_oauthlib | |
parent | d2d971701bd8377ead5f973c96be81042774bd2a (diff) |
Intermediate changes
Diffstat (limited to 'contrib/python/requests-oauthlib/requests_oauthlib')
15 files changed, 78 insertions, 65 deletions
diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/__init__.py b/contrib/python/requests-oauthlib/requests_oauthlib/__init__.py index 0d3e49f9913..a71064cca08 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/__init__.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/__init__.py @@ -1,3 +1,4 @@ +# ruff: noqa: F401 import logging from .oauth1_auth import OAuth1 @@ -5,7 +6,7 @@ from .oauth1_session import OAuth1Session from .oauth2_auth import OAuth2 from .oauth2_session import OAuth2Session, TokenUpdated -__version__ = "1.3.1" +__version__ = "1.4.0" import requests diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/__init__.py b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/__init__.py index 0e8e3ac84f7..8815ea0b8ee 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/__init__.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/__init__.py @@ -1,5 +1,4 @@ -from __future__ import absolute_import - +# ruff: noqa: F401 from .facebook import facebook_compliance_fix from .fitbit import fitbit_compliance_fix from .slack import slack_compliance_fix diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/douban.py b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/douban.py index ecc57b08181..c8b99c721e9 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/douban.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/douban.py @@ -1,14 +1,12 @@ import json -from oauthlib.common import to_unicode - def douban_compliance_fix(session): def fix_token_type(r): token = json.loads(r.text) token.setdefault("token_type", "Bearer") fixed_token = json.dumps(token) - r._content = to_unicode(fixed_token).encode("utf-8") + r._content = fixed_token.encode() return r session._client_default_token_placement = "query" diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/ebay.py b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/ebay.py index 4aa423b3fe8..ef33f39101b 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/ebay.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/ebay.py @@ -1,5 +1,4 @@ import json -from oauthlib.common import to_unicode def ebay_compliance_fix(session): @@ -13,7 +12,7 @@ def ebay_compliance_fix(session): 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") + response._content = fixed_token.encode() return response diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/facebook.py b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/facebook.py index 90e79212728..f44558a8390 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/facebook.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/facebook.py @@ -1,11 +1,5 @@ from json import dumps - -try: - from urlparse import parse_qsl -except ImportError: - from urllib.parse import parse_qsl - -from oauthlib.common import to_unicode +from urllib.parse import parse_qsl def facebook_compliance_fix(session): @@ -26,7 +20,7 @@ def facebook_compliance_fix(session): if expires is not None: token["expires_in"] = expires token["token_type"] = "Bearer" - r._content = to_unicode(dumps(token)).encode("UTF-8") + r._content = dumps(token).encode() return r session.register_compliance_hook("access_token_response", _compliance_fix) diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/fitbit.py b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/fitbit.py index 7e627024017..aacc68bfbb1 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/fitbit.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/fitbit.py @@ -8,8 +8,6 @@ MissingTokenError. from json import loads, dumps -from oauthlib.common import to_unicode - def fitbit_compliance_fix(session): def _missing_error(r): @@ -17,7 +15,7 @@ def fitbit_compliance_fix(session): if "errors" in token: # Set the error to the first one we have token["error"] = token["errors"][0]["errorType"] - r._content = to_unicode(dumps(token)).encode("UTF-8") + r._content = dumps(token).encode() return r session.register_compliance_hook("access_token_response", _missing_error) diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/instagram.py b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/instagram.py index 4e07fe08b57..7d5a2ad447e 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/instagram.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/instagram.py @@ -1,7 +1,4 @@ -try: - from urlparse import urlparse, parse_qs -except ImportError: - from urllib.parse import urlparse, parse_qs +from urllib.parse import urlparse, parse_qs from oauthlib.common import add_params_to_uri diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/mailchimp.py b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/mailchimp.py index c69ce9fdae6..0d602659c64 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/mailchimp.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/mailchimp.py @@ -1,21 +1,19 @@ import json -from oauthlib.common import to_unicode - def mailchimp_compliance_fix(session): def _null_scope(r): token = json.loads(r.text) if "scope" in token and token["scope"] is None: token.pop("scope") - r._content = to_unicode(json.dumps(token)).encode("utf-8") + r._content = json.dumps(token).encode() return r def _non_zero_expiration(r): token = json.loads(r.text) if "expires_in" in token and token["expires_in"] == 0: token["expires_in"] = 3600 - r._content = to_unicode(json.dumps(token)).encode("utf-8") + r._content = json.dumps(token).encode() return r session.register_compliance_hook("access_token_response", _null_scope) diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/plentymarkets.py b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/plentymarkets.py index 9f605f058cc..859f0566a5b 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/plentymarkets.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/plentymarkets.py @@ -1,8 +1,6 @@ from json import dumps, loads import re -from oauthlib.common import to_unicode - def plentymarkets_compliance_fix(session): def _to_snake_case(n): @@ -22,7 +20,7 @@ def plentymarkets_compliance_fix(session): for k, v in token.items(): fixed_token[_to_snake_case(k)] = v - r._content = to_unicode(dumps(fixed_token)).encode("UTF-8") + r._content = dumps(fixed_token).encode() return r session.register_compliance_hook("access_token_response", _compliance_fix) diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/slack.py b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/slack.py index 3f574b03adf..9095a470cd1 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/slack.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/slack.py @@ -1,7 +1,4 @@ -try: - from urlparse import urlparse, parse_qs -except ImportError: - from urllib.parse import urlparse, parse_qs +from urllib.parse import urlparse, parse_qs from oauthlib.common import add_params_to_uri diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/weibo.py b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/weibo.py index 6733abeb15b..f1623fd6d76 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/weibo.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/compliance_fixes/weibo.py @@ -1,13 +1,11 @@ from json import loads, dumps -from oauthlib.common import to_unicode - def weibo_compliance_fix(session): def _missing_token_type(r): token = loads(r.text) token["token_type"] = "Bearer" - r._content = to_unicode(dumps(token)).encode("UTF-8") + r._content = dumps(token).encode() return r session._client.default_token_placement = "query" diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/oauth1_auth.py b/contrib/python/requests-oauthlib/requests_oauthlib/oauth1_auth.py index cfbbd5902c4..f8c0bd6e74e 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/oauth1_auth.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/oauth1_auth.py @@ -1,20 +1,15 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals - import logging from oauthlib.common import extract_params from oauthlib.oauth1 import Client, SIGNATURE_HMAC, SIGNATURE_TYPE_AUTH_HEADER from oauthlib.oauth1 import SIGNATURE_TYPE_BODY -from requests.compat import is_py3 from requests.utils import to_native_string from requests.auth import AuthBase CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded" CONTENT_TYPE_MULTI_PART = "multipart/form-data" -if is_py3: - unicode = str log = logging.getLogger(__name__) @@ -83,7 +78,7 @@ class OAuth1(AuthBase): or self.client.signature_type == SIGNATURE_TYPE_BODY ): content_type = CONTENT_TYPE_FORM_URLENCODED - if not isinstance(content_type, unicode): + if not isinstance(content_type, str): content_type = content_type.decode("utf-8") is_form_encoded = CONTENT_TYPE_FORM_URLENCODED in content_type @@ -96,17 +91,17 @@ class OAuth1(AuthBase): if is_form_encoded: r.headers["Content-Type"] = CONTENT_TYPE_FORM_URLENCODED r.url, headers, r.body = self.client.sign( - unicode(r.url), unicode(r.method), r.body or "", r.headers + str(r.url), str(r.method), r.body or "", r.headers ) elif self.force_include_body: # To allow custom clients to work on non form encoded bodies. r.url, headers, r.body = self.client.sign( - unicode(r.url), unicode(r.method), r.body or "", r.headers + str(r.url), str(r.method), r.body or "", r.headers ) else: # Omit body data in the signing of non form-encoded requests r.url, headers, _ = self.client.sign( - unicode(r.url), unicode(r.method), None, r.headers + str(r.url), str(r.method), None, r.headers ) r.prepare_headers(headers) diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/oauth1_session.py b/contrib/python/requests-oauthlib/requests_oauthlib/oauth1_session.py index 88f2853ca08..7625c8084ee 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/oauth1_session.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/oauth1_session.py @@ -1,9 +1,4 @@ -from __future__ import unicode_literals - -try: - from urlparse import urlparse -except ImportError: - from urllib.parse import urlparse +from urllib.parse import urlparse import logging @@ -85,7 +80,7 @@ class OAuth1Session(requests.Session): 'https://api.twitter.com/oauth/authorize?oauth_token=sdf0o9823sjdfsdf&oauth_callback=https%3A%2F%2F127.0.0.1%2Fcallback' >>> >>> # Third step. Fetch the access token - >>> redirect_response = raw_input('Paste the full redirect URL here.') + >>> redirect_response = input('Paste the full redirect URL here.') >>> oauth_session.parse_authorization_response(redirect_response) { 'oauth_token: 'kjerht2309u', @@ -258,7 +253,7 @@ class OAuth1Session(requests.Session): return add_params_to_uri(url, kwargs.items()) def fetch_request_token(self, url, realm=None, **request_kwargs): - r"""Fetch a request token. + """Fetch a request token. This is the first step in the OAuth 1 workflow. A request token is obtained by making a signed post request to url. The token is then @@ -267,7 +262,7 @@ class OAuth1Session(requests.Session): :param url: The request token endpoint URL. :param realm: A list of realms to request access to. - :param \*\*request_kwargs: Optional arguments passed to ''post'' + :param request_kwargs: Optional arguments passed to ''post'' function in ''requests.Session'' :returns: The response in dict format. diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/oauth2_auth.py b/contrib/python/requests-oauthlib/requests_oauthlib/oauth2_auth.py index b880f72f585..f19f52ac900 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/oauth2_auth.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/oauth2_auth.py @@ -1,4 +1,3 @@ -from __future__ import unicode_literals from oauthlib.oauth2 import WebApplicationClient, InsecureTransportError from oauthlib.oauth2 import is_secure_transport from requests.auth import AuthBase diff --git a/contrib/python/requests-oauthlib/requests_oauthlib/oauth2_session.py b/contrib/python/requests-oauthlib/requests_oauthlib/oauth2_session.py index db4468089bd..93cc4d7bbd2 100644 --- a/contrib/python/requests-oauthlib/requests_oauthlib/oauth2_session.py +++ b/contrib/python/requests-oauthlib/requests_oauthlib/oauth2_session.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import logging from oauthlib.common import generate_token, urldecode @@ -46,6 +44,7 @@ class OAuth2Session(requests.Session): token=None, state=None, token_updater=None, + pkce=None, **kwargs ): """Construct a new OAuth 2 client session. @@ -72,18 +71,23 @@ class OAuth2Session(requests.Session): set a TokenUpdated warning will be raised when a token has been refreshed. This warning will carry the token in its token argument. + :param pkce: Set "S256" or "plain" to enable PKCE. Default is disabled. :param kwargs: Arguments to pass to the Session constructor. """ super(OAuth2Session, self).__init__(**kwargs) self._client = client or WebApplicationClient(client_id, token=token) self.token = token or {} - self.scope = scope + self._scope = scope self.redirect_uri = redirect_uri self.state = state or generate_token self._state = state self.auto_refresh_url = auto_refresh_url self.auto_refresh_kwargs = auto_refresh_kwargs or {} self.token_updater = token_updater + self._pkce = pkce + + if self._pkce not in ["S256", "plain", None]: + raise AttributeError("Wrong value for {}(.., pkce={})".format(self.__class__, self._pkce)) # Ensure that requests doesn't do any automatic auth. See #278. # The default behavior can be re-enabled by setting auth to None. @@ -95,8 +99,24 @@ class OAuth2Session(requests.Session): "access_token_response": set(), "refresh_token_response": set(), "protected_request": set(), + "refresh_token_request": set(), + "access_token_request": set(), } + @property + def scope(self): + """By default the scope from the client is used, except if overridden""" + if self._scope is not None: + return self._scope + elif self._client is not None: + return self._client.scope + else: + return None + + @scope.setter + def scope(self, scope): + self._scope = scope + def new_state(self): """Generates a state string to be used in authorizations.""" try: @@ -161,6 +181,13 @@ class OAuth2Session(requests.Session): :return: authorization_url, state """ state = state or self.new_state() + if self._pkce: + self._code_verifier = self._client.create_code_verifier(43) + kwargs["code_challenge_method"] = self._pkce + kwargs["code_challenge"] = self._client.create_code_challenge( + code_verifier=self._code_verifier, + code_challenge_method=self._pkce + ) return ( self._client.prepare_request_uri( url, @@ -185,7 +212,7 @@ class OAuth2Session(requests.Session): force_querystring=False, timeout=None, headers=None, - verify=True, + verify=None, proxies=None, include_client_id=None, client_secret=None, @@ -252,6 +279,13 @@ class OAuth2Session(requests.Session): "Please supply either code or " "authorization_response parameters." ) + if self._pkce: + if self._code_verifier is None: + raise ValueError( + "Code verifier is not found, authorization URL must be generated before" + ) + kwargs["code_verifier"] = self._code_verifier + # Earlier versions of this library build an HTTPBasicAuth header out of # `username` and `password`. The RFC states, however these attributes # must be in the request body and not the header. @@ -325,7 +359,7 @@ class OAuth2Session(requests.Session): headers = headers or { "Accept": "application/json", - "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", + "Content-Type": "application/x-www-form-urlencoded", } self.token = {} request_kwargs = {} @@ -338,6 +372,12 @@ class OAuth2Session(requests.Session): else: raise ValueError("The method kwarg must be POST or GET.") + for hook in self.compliance_hook["access_token_request"]: + log.debug("Invoking access_token_request hook %s.", hook) + token_url, headers, request_kwargs = hook( + token_url, headers, request_kwargs + ) + r = self.request( method=method, url=token_url, @@ -388,7 +428,7 @@ class OAuth2Session(requests.Session): auth=None, timeout=None, headers=None, - verify=True, + verify=None, proxies=None, **kwargs ): @@ -426,9 +466,13 @@ class OAuth2Session(requests.Session): if headers is None: headers = { "Accept": "application/json", - "Content-Type": ("application/x-www-form-urlencoded;charset=UTF-8"), + "Content-Type": ("application/x-www-form-urlencoded"), } + for hook in self.compliance_hook["refresh_token_request"]: + log.debug("Invoking refresh_token_request hook %s.", hook) + token_url, headers, body = hook(token_url, headers, body) + r = self.post( token_url, data=dict(urldecode(body)), @@ -450,7 +494,7 @@ class OAuth2Session(requests.Session): r = hook(r) self.token = self._client.parse_request_body_response(r.text, scope=self.scope) - if not "refresh_token" in self.token: + if "refresh_token" not in self.token: log.debug("No new refresh token given. Re-using old.") self.token["refresh_token"] = refresh_token return self.token @@ -464,6 +508,7 @@ class OAuth2Session(requests.Session): withhold_token=False, client_id=None, client_secret=None, + files=None, **kwargs ): """Intercept all requests and add the OAuth 2 token if present.""" @@ -519,7 +564,7 @@ class OAuth2Session(requests.Session): log.debug("Supplying headers %s and data %s", headers, data) log.debug("Passing through key word arguments %s.", kwargs) return super(OAuth2Session, self).request( - method, url, headers=headers, data=data, **kwargs + method, url, headers=headers, data=data, files=files, **kwargs ) def register_compliance_hook(self, hook_type, hook): @@ -529,6 +574,8 @@ class OAuth2Session(requests.Session): access_token_response invoked before token parsing. refresh_token_response invoked before refresh token parsing. protected_request invoked before making a request. + access_token_request invoked before making a token fetch request. + refresh_token_request invoked before making a refresh request. If you find a new hook is needed please send a GitHub PR request or open an issue. |