Update oauthlib-3.1.1

This commit is contained in:
JonnyWong16 2021-10-14 22:34:45 -07:00
parent e58aa40099
commit d76838a607
No known key found for this signature in database
GPG key ID: B1F1F9807184697A
64 changed files with 4329 additions and 1421 deletions

View file

@ -6,20 +6,20 @@ oauthlib.oauth2.rfc6749
This module is an implementation of various logic needed
for consuming OAuth 2.0 RFC6749.
"""
from __future__ import absolute_import, unicode_literals
import time
import warnings
from oauthlib.common import generate_token
from oauthlib.oauth2.rfc6749 import tokens
from oauthlib.oauth2.rfc6749.parameters import parse_token_response
from oauthlib.oauth2.rfc6749.parameters import prepare_token_request
from oauthlib.oauth2.rfc6749.parameters import prepare_token_revocation_request
from oauthlib.oauth2.rfc6749.errors import TokenExpiredError
from oauthlib.oauth2.rfc6749.errors import InsecureTransportError
from oauthlib.oauth2.rfc6749.errors import (
InsecureTransportError, TokenExpiredError,
)
from oauthlib.oauth2.rfc6749.parameters import (
parse_token_response, prepare_token_request,
prepare_token_revocation_request,
)
from oauthlib.oauth2.rfc6749.utils import is_secure_transport
AUTH_HEADER = 'auth_header'
URI_QUERY = 'query'
BODY = 'body'
@ -28,8 +28,8 @@ FORM_ENC_HEADERS = {
'Content-Type': 'application/x-www-form-urlencoded'
}
class Client(object):
class Client:
"""Base OAuth2 client responsible for access token management.
This class also acts as a generic interface providing methods common to all
@ -47,6 +47,7 @@ class Client(object):
Python, this is usually :py:class:`oauthlib.oauth2.WebApplicationClient`.
"""
refresh_token_key = 'refresh_token'
def __init__(self, client_id,
default_token_placement=AUTH_HEADER,
@ -80,7 +81,7 @@ class Client(object):
``token`` dict parameter.
:param refresh_token: A refresh token (string) used to refresh expired
tokens. Can also be supplide inside the ``token`` dict parameter.
tokens. Can also be supplied inside the ``token`` dict parameter.
:param mac_key: Encryption key used with MAC tokens.
@ -112,8 +113,10 @@ class Client(object):
self.state_generator = state_generator
self.state = state
self.redirect_url = redirect_url
self.code = None
self.expires_in = None
self._expires_at = None
self._populate_attributes(self.token)
self.populate_token_attributes(self.token)
@property
def token_types(self):
@ -141,6 +144,7 @@ class Client(object):
def parse_request_uri_response(self, *args, **kwargs):
"""Abstract method used to parse redirection responses."""
raise NotImplementedError("Must be implemented by inheriting classes.")
def add_token(self, uri, http_method='GET', body=None, headers=None,
token_placement=None, **kwargs):
@ -174,20 +178,20 @@ class Client(object):
nonce="274312:dj83hs9s",
mac="kDZvddkndxvhGRXZhvuDjEWhGeE="
.. _`I-D.ietf-oauth-v2-bearer`: http://tools.ietf.org/html/rfc6749#section-12.2
.. _`I-D.ietf-oauth-v2-http-mac`: http://tools.ietf.org/html/rfc6749#section-12.2
.. _`I-D.ietf-oauth-v2-bearer`: https://tools.ietf.org/html/rfc6749#section-12.2
.. _`I-D.ietf-oauth-v2-http-mac`: https://tools.ietf.org/html/rfc6749#section-12.2
"""
if not is_secure_transport(uri):
raise InsecureTransportError()
token_placement = token_placement or self.default_token_placement
case_insensitive_token_types = dict(
(k.lower(), v) for k, v in self.token_types.items())
case_insensitive_token_types = {
k.lower(): v for k, v in self.token_types.items()}
if not self.token_type.lower() in case_insensitive_token_types:
raise ValueError("Unsupported token type: %s" % self.token_type)
if not self.access_token:
if not (self.access_token or self.token.get('access_token')):
raise ValueError("Missing access token.")
if self._expires_at and self._expires_at < time.time():
@ -197,7 +201,7 @@ class Client(object):
headers, token_placement, **kwargs)
def prepare_authorization_request(self, authorization_url, state=None,
redirect_url=None, scope=None, **kwargs):
redirect_url=None, scope=None, **kwargs):
"""Prepare the authorization request.
This is the first step in many OAuth flows in which the user is
@ -218,6 +222,11 @@ class Client(object):
the provider. If provided then it must also be provided in the
token request.
:param scope: List of scopes to request. Must be equal to
or a subset of the scopes granted when obtaining the refresh
token. If none is provided, the ones provided in the constructor are
used.
:param kwargs: Additional parameters to included in the request.
:returns: The prepared request tuple with (url, headers, body).
@ -227,14 +236,15 @@ class Client(object):
self.state = state or self.state_generator()
self.redirect_url = redirect_url or self.redirect_url
self.scope = scope or self.scope
# do not assign scope to self automatically anymore
scope = self.scope if scope is None else scope
auth_url = self.prepare_request_uri(
authorization_url, redirect_uri=self.redirect_url,
scope=self.scope, state=self.state, **kwargs)
authorization_url, redirect_uri=self.redirect_url,
scope=scope, state=self.state, **kwargs)
return auth_url, FORM_ENC_HEADERS, ''
def prepare_token_request(self, token_url, authorization_response=None,
redirect_url=None, state=None, body='', **kwargs):
redirect_url=None, state=None, body='', **kwargs):
"""Prepare a token creation request.
Note that these requests usually require client authentication, either
@ -251,7 +261,10 @@ class Client(object):
:param redirect_url: The redirect_url supplied with the authorization
request (if there was one).
:param body: Request body (URL encoded string).
:param state:
:param body: Existing request body (URL encoded string) to embed parameters
into. This may contain extra paramters. Default ''.
:param kwargs: Additional parameters to included in the request.
@ -263,15 +276,15 @@ class Client(object):
state = state or self.state
if authorization_response:
self.parse_request_uri_response(
authorization_response, state=state)
authorization_response, state=state)
self.redirect_url = redirect_url or self.redirect_url
body = self.prepare_request_body(body=body,
redirect_uri=self.redirect_url, **kwargs)
redirect_uri=self.redirect_url, **kwargs)
return token_url, FORM_ENC_HEADERS, body
def prepare_refresh_token_request(self, token_url, refresh_token=None,
body='', scope=None, **kwargs):
body='', scope=None, **kwargs):
"""Prepare an access token refresh request.
Expired access tokens can be replaced by new access tokens without
@ -283,11 +296,13 @@ class Client(object):
:param refresh_token: Refresh token string.
:param body: Request body (URL encoded string).
:param body: Existing request body (URL encoded string) to embed parameters
into. This may contain extra paramters. Default ''.
:param scope: List of scopes to request. Must be equal to
or a subset of the scopes granted when obtaining the refresh
token.
token. If none is provided, the ones provided in the constructor are
used.
:param kwargs: Additional parameters to included in the request.
@ -296,13 +311,14 @@ class Client(object):
if not is_secure_transport(token_url):
raise InsecureTransportError()
self.scope = scope or self.scope
# do not assign scope to self automatically anymore
scope = self.scope if scope is None else scope
body = self.prepare_refresh_body(body=body,
refresh_token=refresh_token, scope=self.scope, **kwargs)
refresh_token=refresh_token, scope=scope, **kwargs)
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='', callback=None, **kwargs):
"""Prepare a token revocation request.
:param revocation_url: Provider token revocation endpoint URL.
@ -313,6 +329,8 @@ class Client(object):
``"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.
@ -357,8 +375,8 @@ class Client(object):
raise InsecureTransportError()
return prepare_token_revocation_request(revocation_url, token,
token_type_hint=token_type_hint, body=body, callback=callback,
**kwargs)
token_type_hint=token_type_hint, body=body, callback=callback,
**kwargs)
def parse_request_body_response(self, body, scope=None, **kwargs):
"""Parse the JSON response body.
@ -370,7 +388,8 @@ class Client(object):
returns an error response as described in `Section 5.2`_.
:param body: The response body from the token request.
:param scope: Scopes originally requested.
:param scope: Scopes originally requested. If none is provided, the ones
provided in the constructor are used.
:return: Dictionary of token parameters.
:raises: Warning if scope has changed. OAuth2Error if response is invalid.
@ -398,16 +417,17 @@ class Client(object):
If omitted, the authorization server SHOULD provide the
expiration time via other means or document the default value.
**scope**
**scope**
Providers may supply this in all responses but are required to only
if it has changed since the authorization request.
.. _`Section 5.1`: http://tools.ietf.org/html/rfc6749#section-5.1
.. _`Section 5.2`: http://tools.ietf.org/html/rfc6749#section-5.2
.. _`Section 7.1`: http://tools.ietf.org/html/rfc6749#section-7.1
.. _`Section 5.1`: https://tools.ietf.org/html/rfc6749#section-5.1
.. _`Section 5.2`: https://tools.ietf.org/html/rfc6749#section-5.2
.. _`Section 7.1`: https://tools.ietf.org/html/rfc6749#section-7.1
"""
scope = self.scope if scope is None else scope
self.token = parse_token_response(body, scope=scope)
self._populate_attributes(self.token)
self.populate_token_attributes(self.token)
return self.token
def prepare_refresh_body(self, body='', refresh_token=None, scope=None, **kwargs):
@ -427,10 +447,12 @@ class Client(object):
Section 3.3. The requested scope MUST NOT include any scope
not originally granted by the resource owner, and if omitted is
treated as equal to the scope originally granted by the
resource owner.
resource owner. Note that if none is provided, the ones provided
in the constructor are used if any.
"""
refresh_token = refresh_token or self.refresh_token
return prepare_token_request('refresh_token', body=body, scope=scope,
scope = self.scope if scope is None else scope
return prepare_token_request(self.refresh_token_key, body=body, scope=scope,
refresh_token=refresh_token, **kwargs)
def _add_bearer_token(self, uri, http_method='GET', body=None,
@ -455,13 +477,27 @@ class Client(object):
Warning: MAC token support is experimental as the spec is not yet stable.
"""
if token_placement != AUTH_HEADER:
raise ValueError("Invalid token placement.")
headers = tokens.prepare_mac_header(self.access_token, uri,
self.mac_key, http_method, headers=headers, body=body, ext=ext,
hash_algorithm=self.mac_algorithm, **kwargs)
return uri, headers, body
def _populate_attributes(self, response):
"""Add commonly used values such as access_token to self."""
warnings.warn("Please switch to the public method "
"populate_token_attributes.", DeprecationWarning)
return self.populate_token_attributes(response)
def populate_code_attributes(self, response):
"""Add attributes from an auth code response to self."""
if 'code' in response:
self.code = response.get('code')
def populate_token_attributes(self, response):
"""Add attributes from a token exchange response to self."""
if 'access_token' in response:
self.access_token = response.get('access_token')
@ -479,12 +515,8 @@ class Client(object):
if 'expires_at' in response:
self._expires_at = int(response.get('expires_at'))
if 'code' in response:
self.code = response.get('code')
if 'mac_key' in response:
self.mac_key = response.get('mac_key')
if 'mac_algorithm' in response:
self.mac_algorithm = response.get('mac_algorithm')