about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients')
-rw-r--r--.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/__init__.py14
-rw-r--r--.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/backend_application.py74
-rw-r--r--.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/base.py604
-rw-r--r--.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/legacy_application.py84
-rw-r--r--.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/mobile_application.py174
-rw-r--r--.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/service_application.py189
-rw-r--r--.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/web_application.py222
7 files changed, 1361 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/__init__.py b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/__init__.py
new file mode 100644
index 00000000..8fc6c955
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/__init__.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+"""
+oauthlib.oauth2.rfc6749
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This module is an implementation of various logic needed
+for consuming OAuth 2.0 RFC6749.
+"""
+from .backend_application import BackendApplicationClient
+from .base import AUTH_HEADER, BODY, URI_QUERY, Client
+from .legacy_application import LegacyApplicationClient
+from .mobile_application import MobileApplicationClient
+from .service_application import ServiceApplicationClient
+from .web_application import WebApplicationClient
diff --git a/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/backend_application.py b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/backend_application.py
new file mode 100644
index 00000000..e11e8fae
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/backend_application.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+"""
+oauthlib.oauth2.rfc6749
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This module is an implementation of various logic needed
+for consuming and providing OAuth 2.0 RFC6749.
+"""
+from ..parameters import prepare_token_request
+from .base import Client
+
+
+class BackendApplicationClient(Client):
+
+    """A public client utilizing the client credentials grant workflow.
+
+    The client can request an access token using only its client
+    credentials (or other supported means of authentication) when the
+    client is requesting access to the protected resources under its
+    control, or those of another resource owner which has been previously
+    arranged with the authorization server (the method of which is beyond
+    the scope of this specification).
+
+    The client credentials grant type MUST only be used by confidential
+    clients.
+
+    Since the client authentication is used as the authorization grant,
+    no additional authorization request is needed.
+    """
+
+    grant_type = 'client_credentials'
+
+    def prepare_request_body(self, body='', scope=None,
+                             include_client_id=False, **kwargs):
+        """Add the client credentials to the request body.
+
+        The client makes a request to the token endpoint by adding the
+        following parameters using the "application/x-www-form-urlencoded"
+        format per `Appendix B`_ in the HTTP request entity-body:
+
+        :param body: Existing request body (URL encoded string) to embed parameters
+                     into. This may contain extra parameters. Default ''.
+        :param scope:   The scope of the access request as described by
+                        `Section 3.3`_.
+
+        :param include_client_id: `True` to send the `client_id` in the
+                                  body of the upstream request. This is required
+                                  if the client is not authenticating with the
+                                  authorization server as described in
+                                  `Section 3.2.1`_. False otherwise (default).
+        :type include_client_id: Boolean
+
+        :param kwargs:  Extra credentials to include in the token request.
+
+        The client MUST authenticate with the authorization server as
+        described in `Section 3.2.1`_.
+
+        The prepared body will include all provided credentials as well as
+        the ``grant_type`` parameter set to ``client_credentials``::
+
+            >>> from oauthlib.oauth2 import BackendApplicationClient
+            >>> client = BackendApplicationClient('your_id')
+            >>> client.prepare_request_body(scope=['hello', 'world'])
+            'grant_type=client_credentials&scope=hello+world'
+
+        .. _`Appendix B`: https://tools.ietf.org/html/rfc6749#appendix-B
+        .. _`Section 3.3`: https://tools.ietf.org/html/rfc6749#section-3.3
+        .. _`Section 3.2.1`: https://tools.ietf.org/html/rfc6749#section-3.2.1
+        """
+        kwargs['client_id'] = self.client_id
+        kwargs['include_client_id'] = include_client_id
+        scope = self.scope if scope is None else scope
+        return prepare_token_request(self.grant_type, body=body,
+                                     scope=scope, **kwargs)
diff --git a/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/base.py b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/base.py
new file mode 100644
index 00000000..d5eb0cc1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/base.py
@@ -0,0 +1,604 @@
+# -*- coding: utf-8 -*-
+"""
+oauthlib.oauth2.rfc6749
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This module is an implementation of various logic needed
+for consuming OAuth 2.0 RFC6749.
+"""
+import base64
+import hashlib
+import re
+import secrets
+import time
+import warnings
+
+from oauthlib.common import generate_token
+from oauthlib.oauth2.rfc6749 import tokens
+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'
+
+FORM_ENC_HEADERS = {
+    'Content-Type': 'application/x-www-form-urlencoded'
+}
+
+
+class Client:
+    """Base OAuth2 client responsible for access token management.
+
+    This class also acts as a generic interface providing methods common to all
+    client types such as ``prepare_authorization_request`` and
+    ``prepare_token_revocation_request``. The ``prepare_x_request`` methods are
+    the recommended way of interacting with clients (as opposed to the abstract
+    prepare uri/body/etc methods). They are recommended over the older set
+    because they are easier to use (more consistent) and add a few additional
+    security checks, such as HTTPS and state checking.
+
+    Some of these methods require further implementation only provided by the
+    specific purpose clients such as
+    :py:class:`oauthlib.oauth2.MobileApplicationClient` and thus you should always
+    seek to use the client class matching the OAuth workflow you need. For
+    Python, this is usually :py:class:`oauthlib.oauth2.WebApplicationClient`.
+
+    """
+    refresh_token_key = 'refresh_token'
+
+    def __init__(self, client_id,
+                 default_token_placement=AUTH_HEADER,
+                 token_type='Bearer',
+                 access_token=None,
+                 refresh_token=None,
+                 mac_key=None,
+                 mac_algorithm=None,
+                 token=None,
+                 scope=None,
+                 state=None,
+                 redirect_url=None,
+                 state_generator=generate_token,
+                 code_verifier=None,
+                 code_challenge=None,
+                 code_challenge_method=None,
+                 **kwargs):
+        """Initialize a client with commonly used attributes.
+
+        :param client_id: Client identifier given by the OAuth provider upon
+        registration.
+
+        :param default_token_placement: Tokens can be supplied in the Authorization
+        header (default), the URL query component (``query``) or the request
+        body (``body``).
+
+        :param token_type: OAuth 2 token type. Defaults to Bearer. Change this
+        if you specify the ``access_token`` parameter and know it is of a
+        different token type, such as a MAC, JWT or SAML token. Can
+        also be supplied as ``token_type`` inside the ``token`` dict parameter.
+
+        :param access_token: An access token (string) used to authenticate
+        requests to protected resources. Can also be supplied inside the
+        ``token`` dict parameter.
+
+        :param refresh_token: A refresh token (string) used to refresh expired
+        tokens. Can also be supplied inside the ``token`` dict parameter.
+
+        :param mac_key: Encryption key used with MAC tokens.
+
+        :param mac_algorithm:  Hashing algorithm for MAC tokens.
+
+        :param token: A dict of token attributes such as ``access_token``,
+        ``token_type`` and ``expires_at``.
+
+        :param scope: A list of default scopes to request authorization for.
+
+        :param state: A CSRF protection string used during authorization.
+
+        :param redirect_url: The redirection endpoint on the client side to which
+        the user returns after authorization.
+
+        :param state_generator: A no argument state generation callable. Defaults
+        to :py:meth:`oauthlib.common.generate_token`.
+
+        :param code_verifier: PKCE parameter. A cryptographically random string that is used to correlate the
+        authorization request to the token request.
+
+        :param code_challenge: PKCE parameter. A challenge derived from the code verifier that is sent in the
+        authorization request, to be verified against later.
+
+        :param code_challenge_method: PKCE parameter. A method that was used to derive code challenge.
+        Defaults to "plain" if not present in the request.
+        """
+
+        self.client_id = client_id
+        self.default_token_placement = default_token_placement
+        self.token_type = token_type
+        self.access_token = access_token
+        self.refresh_token = refresh_token
+        self.mac_key = mac_key
+        self.mac_algorithm = mac_algorithm
+        self.token = token or {}
+        self.scope = scope
+        self.state_generator = state_generator
+        self.state = state
+        self.redirect_url = redirect_url
+        self.code_verifier = code_verifier
+        self.code_challenge = code_challenge
+        self.code_challenge_method = code_challenge_method
+        self.code = None
+        self.expires_in = None
+        self._expires_at = None
+        self.populate_token_attributes(self.token)
+
+    @property
+    def token_types(self):
+        """Supported token types and their respective methods
+
+        Additional tokens can be supported by extending this dictionary.
+
+        The Bearer token spec is stable and safe to use.
+
+        The MAC token spec is not yet stable and support for MAC tokens
+        is experimental and currently matching version 00 of the spec.
+        """
+        return {
+            'Bearer': self._add_bearer_token,
+            'MAC': self._add_mac_token
+        }
+
+    def prepare_request_uri(self, *args, **kwargs):
+        """Abstract method used to create request URIs."""
+        raise NotImplementedError("Must be implemented by inheriting classes.")
+
+    def prepare_request_body(self, *args, **kwargs):
+        """Abstract method used to create request bodies."""
+        raise NotImplementedError("Must be implemented by inheriting classes.")
+
+    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):
+        """Add token to the request uri, body or authorization header.
+
+        The access token type provides the client with the information
+        required to successfully utilize the access token to make a protected
+        resource request (along with type-specific attributes).  The client
+        MUST NOT use an access token if it does not understand the token
+        type.
+
+        For example, the "bearer" token type defined in
+        [`I-D.ietf-oauth-v2-bearer`_] is utilized by simply including the access
+        token string in the request:
+
+        .. code-block:: http
+
+            GET /resource/1 HTTP/1.1
+            Host: example.com
+            Authorization: Bearer mF_9.B5f-4.1JqM
+
+        while the "mac" token type defined in [`I-D.ietf-oauth-v2-http-mac`_] is
+        utilized by issuing a MAC key together with the access token which is
+        used to sign certain components of the HTTP requests:
+
+        .. code-block:: http
+
+            GET /resource/1 HTTP/1.1
+            Host: example.com
+            Authorization: MAC id="h480djs93hd8",
+                                nonce="274312:dj83hs9s",
+                                mac="kDZvddkndxvhGRXZhvuDjEWhGeE="
+
+        .. _`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 = {
+            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 or self.token.get('access_token')):
+            raise ValueError("Missing access token.")
+
+        if self._expires_at and self._expires_at < time.time():
+            raise TokenExpiredError()
+
+        return case_insensitive_token_types[self.token_type.lower()](uri, http_method, body,
+                                                                     headers, token_placement, **kwargs)
+
+    def prepare_authorization_request(self, authorization_url, state=None,
+                                      redirect_url=None, scope=None, **kwargs):
+        """Prepare the authorization request.
+
+        This is the first step in many OAuth flows in which the user is
+        redirected to a certain authorization URL. This method adds
+        required parameters to the authorization URL.
+
+        :param authorization_url: Provider authorization endpoint URL.
+        :param state: CSRF protection string. Will be automatically created if
+            not provided. The generated state is available via the ``state``
+            attribute. Clients should verify that the state is unchanged and
+            present in the authorization response. This verification is done
+            automatically if using the ``authorization_response`` parameter
+            with ``prepare_token_request``.
+        :param redirect_url: Redirect URL to which the user will be returned
+            after authorization. Must be provided unless previously setup with
+            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).
+        """
+        if not is_secure_transport(authorization_url):
+            raise InsecureTransportError()
+
+        self.state = state or self.state_generator()
+        self.redirect_url = redirect_url or self.redirect_url
+        # 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=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):
+        """Prepare a token creation request.
+
+        Note that these requests usually require client authentication, either
+        by including client_id or a set of provider specific authentication
+        credentials.
+
+        :param token_url: Provider token creation endpoint URL.
+        :param authorization_response: The full redirection URL string, i.e.
+            the location to which the user was redirected after successful
+            authorization. Used to mine credentials needed to obtain a token
+            in this step, such as authorization code.
+        :param redirect_url: The redirect_url supplied with the authorization
+            request (if there was one).
+        :param state:
+        :param body: Existing request body (URL encoded string) to embed parameters
+                     into. This may contain extra parameters. Default ''.
+        :param kwargs: Additional parameters to included in the request.
+        :returns: The prepared request tuple with (url, headers, body).
+        """
+        if not is_secure_transport(token_url):
+            raise InsecureTransportError()
+
+        state = state or self.state
+        if authorization_response:
+            self.parse_request_uri_response(
+                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)
+
+        return token_url, FORM_ENC_HEADERS, body
+
+    def prepare_refresh_token_request(self, token_url, refresh_token=None,
+                                      body='', scope=None, **kwargs):
+        """Prepare an access token refresh request.
+
+        Expired access tokens can be replaced by new access tokens without
+        going through the OAuth dance if the client obtained a refresh token.
+        This refresh token and authentication credentials can be used to
+        obtain a new access token, and possibly a new refresh token.
+
+        :param token_url: Provider token refresh endpoint URL.
+        :param refresh_token: Refresh token string.
+        :param body: Existing request body (URL encoded string) to embed parameters
+            into. This may contain extra parameters. Default ''.
+        :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).
+        """
+        if not is_secure_transport(token_url):
+            raise InsecureTransportError()
+
+        # 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=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):
+        """Prepare a token revocation request.
+
+        :param revocation_url: Provider token revocation endpoint URL.
+        :param token: The access or refresh token to be revoked (string).
+        :param token_type_hint: ``"access_token"`` (default) or
+            ``"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
+
+            POST /revoke HTTP/1.1
+            Host: server.example.com
+            Content-Type: application/x-www-form-urlencoded
+            Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
+
+            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.
+        """
+        if not is_secure_transport(revocation_url):
+            raise InsecureTransportError()
+
+        return prepare_token_revocation_request(revocation_url, token,
+                                                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.
+
+        If the access token request is valid and authorized, the
+        authorization server issues an access token as described in
+        `Section 5.1`_.  A refresh token SHOULD NOT be included.  If the request
+        failed client authentication or is invalid, the authorization server
+        returns an error response as described in `Section 5.2`_.
+
+        :param body: The response body from the token request.
+        :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. :py:class:`oauthlib.oauth2.errors.OAuth2Error`
+            if response is invalid.
+
+        These response are json encoded and could easily be parsed without
+        the assistance of OAuthLib. However, there are a few subtle issues
+        to be aware of regarding the response which are helpfully addressed
+        through the raising of various errors.
+
+        A successful response should always contain
+
+        **access_token**
+                The access token issued by the authorization server. Often
+                a random string.
+
+        **token_type**
+            The type of the token issued as described in `Section 7.1`_.
+            Commonly ``Bearer``.
+
+        While it is not mandated it is recommended that the provider include
+
+        **expires_in**
+            The lifetime in seconds of the access token.  For
+            example, the value "3600" denotes that the access token will
+            expire in one hour from the time the response was generated.
+            If omitted, the authorization server SHOULD provide the
+            expiration time via other means or document the default value.
+
+         **scope**
+            Providers may supply this in all responses but are required to only
+            if it has changed since the authorization request.
+
+        .. _`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_token_attributes(self.token)
+        return self.token
+
+    def prepare_refresh_body(self, body='', refresh_token=None, scope=None, **kwargs):
+        """Prepare an access token request, using a refresh token.
+
+        If the authorization server issued a refresh token to the client, the
+        client makes a refresh request to the token endpoint by adding the
+        following parameters using the `application/x-www-form-urlencoded`
+        format in the HTTP request entity-body:
+
+        :param refresh_token: REQUIRED.  The refresh token issued to the client.
+        :param scope:  OPTIONAL.  The scope of the access request as described by
+            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. Note that if none is provided, the ones provided
+            in the constructor are used if any.
+        """
+        refresh_token = refresh_token or self.refresh_token
+        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,
+                          headers=None, token_placement=None):
+        """Add a bearer token to the request uri, body or authorization header."""
+        if token_placement == AUTH_HEADER:
+            headers = tokens.prepare_bearer_headers(self.access_token, headers)
+
+        elif token_placement == URI_QUERY:
+            uri = tokens.prepare_bearer_uri(self.access_token, uri)
+
+        elif token_placement == BODY:
+            body = tokens.prepare_bearer_body(self.access_token, body)
+
+        else:
+            raise ValueError("Invalid token placement.")
+        return uri, headers, body
+
+    def create_code_verifier(self, length):
+        """Create PKCE **code_verifier** used in computing **code_challenge**. 
+        See `RFC7636 Section 4.1`_
+
+        :param length: REQUIRED. The length of the code_verifier.
+
+        The client first creates a code verifier, "code_verifier", for each
+        OAuth 2.0 [RFC6749] Authorization Request, in the following manner:
+
+        .. code-block:: text
+
+               code_verifier = high-entropy cryptographic random STRING using the
+               unreserved characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
+               from Section 2.3 of [RFC3986], with a minimum length of 43 characters
+               and a maximum length of 128 characters.
+
+        .. _`RFC7636 Section 4.1`: https://tools.ietf.org/html/rfc7636#section-4.1
+        """
+        code_verifier = None
+
+        if not length >= 43:
+            raise ValueError("Length must be greater than or equal to 43")
+
+        if not length <= 128:
+            raise ValueError("Length must be less than or equal to 128")
+
+        allowed_characters = re.compile('^[A-Zaa-z0-9-._~]')
+        code_verifier = secrets.token_urlsafe(length)
+
+        if not re.search(allowed_characters, code_verifier):
+            raise ValueError("code_verifier contains invalid characters")
+
+        self.code_verifier = code_verifier
+
+        return code_verifier
+
+    def create_code_challenge(self, code_verifier, code_challenge_method=None):
+        """Create PKCE **code_challenge** derived from the  **code_verifier**.
+        See `RFC7636 Section 4.2`_
+
+        :param code_verifier: REQUIRED. The **code_verifier** generated from `create_code_verifier()`.
+        :param code_challenge_method: OPTIONAL. The method used to derive the **code_challenge**. Acceptable values include `S256`. DEFAULT is `plain`.
+
+               The client then creates a code challenge derived from the code
+               verifier by using one of the following transformations on the code
+               verifier::
+
+                   plain
+                      code_challenge = code_verifier
+                   S256
+                      code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
+
+               If the client is capable of using `S256`, it MUST use `S256`, as
+               `S256` is Mandatory To Implement (MTI) on the server.  Clients are
+               permitted to use `plain` only if they cannot support `S256` for some
+               technical reason and know via out-of-band configuration that the
+               server supports `plain`.
+
+               The plain transformation is for compatibility with existing
+               deployments and for constrained environments that can't use the S256 transformation.
+
+        .. _`RFC7636 Section 4.2`: https://tools.ietf.org/html/rfc7636#section-4.2
+        """
+        code_challenge = None
+
+        if code_verifier == None:
+            raise ValueError("Invalid code_verifier")
+
+        if code_challenge_method == None:
+            code_challenge_method = "plain"
+            self.code_challenge_method = code_challenge_method
+            code_challenge = code_verifier
+            self.code_challenge = code_challenge
+
+        if code_challenge_method == "S256":
+            h = hashlib.sha256()
+            h.update(code_verifier.encode(encoding='ascii'))
+            sha256_val = h.digest()
+            code_challenge = bytes.decode(base64.urlsafe_b64encode(sha256_val))
+            # replace '+' with '-', '/' with '_', and remove trailing '='
+            code_challenge = code_challenge.replace("+", "-").replace("/", "_").replace("=", "")
+            self.code_challenge = code_challenge
+
+        return code_challenge
+
+    def _add_mac_token(self, uri, http_method='GET', body=None,
+                       headers=None, token_placement=AUTH_HEADER, ext=None, **kwargs):
+        """Add a MAC token to the request authorization header.
+
+        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):
+        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')
+
+        if 'refresh_token' in response:
+            self.refresh_token = response.get('refresh_token')
+
+        if 'token_type' in response:
+            self.token_type = response.get('token_type')
+
+        if 'expires_in' in response:
+            self.expires_in = response.get('expires_in')
+            self._expires_at = time.time() + int(self.expires_in)
+
+        if 'expires_at' in response:
+            try:
+                self._expires_at = int(response.get('expires_at'))
+            except:
+                self._expires_at = None
+
+        if 'mac_key' in response:
+            self.mac_key = response.get('mac_key')
+
+        if 'mac_algorithm' in response:
+            self.mac_algorithm = response.get('mac_algorithm')
diff --git a/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/legacy_application.py b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/legacy_application.py
new file mode 100644
index 00000000..9920981d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/legacy_application.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+"""
+oauthlib.oauth2.rfc6749
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This module is an implementation of various logic needed
+for consuming and providing OAuth 2.0 RFC6749.
+"""
+from ..parameters import prepare_token_request
+from .base import Client
+
+
+class LegacyApplicationClient(Client):
+
+    """A public client using the resource owner password and username directly.
+
+    The resource owner password credentials grant type is suitable in
+    cases where the resource owner has a trust relationship with the
+    client, such as the device operating system or a highly privileged
+    application.  The authorization server should take special care when
+    enabling this grant type, and only allow it when other flows are not
+    viable.
+
+    The grant type is suitable for clients capable of obtaining the
+    resource owner's credentials (username and password, typically using
+    an interactive form).  It is also used to migrate existing clients
+    using direct authentication schemes such as HTTP Basic or Digest
+    authentication to OAuth by converting the stored credentials to an
+    access token.
+
+    The method through which the client obtains the resource owner
+    credentials is beyond the scope of this specification.  The client
+    MUST discard the credentials once an access token has been obtained.
+    """
+
+    grant_type = 'password'
+
+    def __init__(self, client_id, **kwargs):
+        super().__init__(client_id, **kwargs)
+
+    def prepare_request_body(self, username, password, body='', scope=None,
+                             include_client_id=False, **kwargs):
+        """Add the resource owner password and username to the request body.
+
+        The client makes a request to the token endpoint by adding the
+        following parameters using the "application/x-www-form-urlencoded"
+        format per `Appendix B`_ in the HTTP request entity-body:
+
+        :param username:    The resource owner username.
+        :param password:    The resource owner password.
+        :param body: Existing request body (URL encoded string) to embed parameters
+                     into. This may contain extra parameters. Default ''.
+        :param scope:   The scope of the access request as described by
+                        `Section 3.3`_.
+        :param include_client_id: `True` to send the `client_id` in the
+                                  body of the upstream request. This is required
+                                  if the client is not authenticating with the
+                                  authorization server as described in
+                                  `Section 3.2.1`_. False otherwise (default).
+        :type include_client_id: Boolean
+        :param kwargs:  Extra credentials to include in the token request.
+
+        If the client type is confidential or the client was issued client
+        credentials (or assigned other authentication requirements), the
+        client MUST authenticate with the authorization server as described
+        in `Section 3.2.1`_.
+
+        The prepared body will include all provided credentials as well as
+        the ``grant_type`` parameter set to ``password``::
+
+            >>> from oauthlib.oauth2 import LegacyApplicationClient
+            >>> client = LegacyApplicationClient('your_id')
+            >>> client.prepare_request_body(username='foo', password='bar', scope=['hello', 'world'])
+            'grant_type=password&username=foo&scope=hello+world&password=bar'
+
+        .. _`Appendix B`: https://tools.ietf.org/html/rfc6749#appendix-B
+        .. _`Section 3.3`: https://tools.ietf.org/html/rfc6749#section-3.3
+        .. _`Section 3.2.1`: https://tools.ietf.org/html/rfc6749#section-3.2.1
+        """
+        kwargs['client_id'] = self.client_id
+        kwargs['include_client_id'] = include_client_id
+        scope = self.scope if scope is None else scope
+        return prepare_token_request(self.grant_type, body=body, username=username,
+                                     password=password, scope=scope, **kwargs)
diff --git a/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/mobile_application.py b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/mobile_application.py
new file mode 100644
index 00000000..b10b41ce
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/mobile_application.py
@@ -0,0 +1,174 @@
+# -*- coding: utf-8 -*-
+"""
+oauthlib.oauth2.rfc6749
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This module is an implementation of various logic needed
+for consuming and providing OAuth 2.0 RFC6749.
+"""
+from ..parameters import parse_implicit_response, prepare_grant_uri
+from .base import Client
+
+
+class MobileApplicationClient(Client):
+
+    """A public client utilizing the implicit code grant workflow.
+
+    A user-agent-based application is a public client in which the
+    client code is downloaded from a web server and executes within a
+    user-agent (e.g. web browser) on the device used by the resource
+    owner.  Protocol data and credentials are easily accessible (and
+    often visible) to the resource owner.  Since such applications
+    reside within the user-agent, they can make seamless use of the
+    user-agent capabilities when requesting authorization.
+
+    The implicit grant type is used to obtain access tokens (it does not
+    support the issuance of refresh tokens) and is optimized for public
+    clients known to operate a particular redirection URI.  These clients
+    are typically implemented in a browser using a scripting language
+    such as JavaScript.
+
+    As a redirection-based flow, the client must be capable of
+    interacting with the resource owner's user-agent (typically a web
+    browser) and capable of receiving incoming requests (via redirection)
+    from the authorization server.
+
+    Unlike the authorization code grant type in which the client makes
+    separate requests for authorization and access token, the client
+    receives the access token as the result of the authorization request.
+
+    The implicit grant type does not include client authentication, and
+    relies on the presence of the resource owner and the registration of
+    the redirection URI.  Because the access token is encoded into the
+    redirection URI, it may be exposed to the resource owner and other
+    applications residing on the same device.
+    """
+    
+    response_type = 'token'
+
+    def prepare_request_uri(self, uri, redirect_uri=None, scope=None,
+                            state=None, **kwargs):
+        """Prepare the implicit grant request URI.
+
+        The client constructs the request URI by adding the following
+        parameters to the query component of the authorization endpoint URI
+        using the "application/x-www-form-urlencoded" format, per `Appendix B`_:
+
+        :param redirect_uri:  OPTIONAL. The redirect URI must be an absolute URI
+                              and it should have been registered with the OAuth
+                              provider prior to use. As described in `Section 3.1.2`_.
+
+        :param scope:  OPTIONAL. The scope of the access request as described by
+                       Section 3.3`_. These may be any string but are commonly
+                       URIs or various categories such as ``videos`` or ``documents``.
+
+        :param state:   RECOMMENDED.  An opaque value used by the client to maintain
+                        state between the request and callback.  The authorization
+                        server includes this value when redirecting the user-agent back
+                        to the client.  The parameter SHOULD be used for preventing
+                        cross-site request forgery as described in `Section 10.12`_.
+
+        :param kwargs:  Extra arguments to include in the request URI.
+
+        In addition to supplied parameters, OAuthLib will append the ``client_id``
+        that was provided in the constructor as well as the mandatory ``response_type``
+        argument, set to ``token``::
+
+            >>> from oauthlib.oauth2 import MobileApplicationClient
+            >>> client = MobileApplicationClient('your_id')
+            >>> client.prepare_request_uri('https://example.com')
+            'https://example.com?client_id=your_id&response_type=token'
+            >>> client.prepare_request_uri('https://example.com', redirect_uri='https://a.b/callback')
+            'https://example.com?client_id=your_id&response_type=token&redirect_uri=https%3A%2F%2Fa.b%2Fcallback'
+            >>> client.prepare_request_uri('https://example.com', scope=['profile', 'pictures'])
+            'https://example.com?client_id=your_id&response_type=token&scope=profile+pictures'
+            >>> client.prepare_request_uri('https://example.com', foo='bar')
+            'https://example.com?client_id=your_id&response_type=token&foo=bar'
+
+        .. _`Appendix B`: https://tools.ietf.org/html/rfc6749#appendix-B
+        .. _`Section 2.2`: https://tools.ietf.org/html/rfc6749#section-2.2
+        .. _`Section 3.1.2`: https://tools.ietf.org/html/rfc6749#section-3.1.2
+        .. _`Section 3.3`: https://tools.ietf.org/html/rfc6749#section-3.3
+        .. _`Section 10.12`: https://tools.ietf.org/html/rfc6749#section-10.12
+        """
+        scope = self.scope if scope is None else scope
+        return prepare_grant_uri(uri, self.client_id, self.response_type,
+                                 redirect_uri=redirect_uri, state=state, scope=scope, **kwargs)
+
+    def parse_request_uri_response(self, uri, state=None, scope=None):
+        """Parse the response URI fragment.
+
+        If the resource owner grants the access request, the authorization
+        server issues an access token and delivers it to the client by adding
+        the following parameters to the fragment component of the redirection
+        URI using the "application/x-www-form-urlencoded" format:
+
+        :param uri: The callback URI that resulted from the user being redirected
+                    back from the provider to you, the client.
+        :param state: The state provided in the authorization request.
+        :param scope: The scopes provided in the authorization request.
+        :return: Dictionary of token parameters.
+        :raises: OAuth2Error if response is invalid.
+
+        A successful response should always contain
+
+        **access_token**
+                The access token issued by the authorization server. Often
+                a random string.
+
+        **token_type**
+            The type of the token issued as described in `Section 7.1`_.
+            Commonly ``Bearer``.
+
+        **state**
+            If you provided the state parameter in the authorization phase, then
+            the provider is required to include that exact state value in the
+            response.
+
+        While it is not mandated it is recommended that the provider include
+
+        **expires_in**
+            The lifetime in seconds of the access token.  For
+            example, the value "3600" denotes that the access token will
+            expire in one hour from the time the response was generated.
+            If omitted, the authorization server SHOULD provide the
+            expiration time via other means or document the default value.
+
+        **scope**
+            Providers may supply this in all responses but are required to only
+            if it has changed since the authorization request.
+
+        A few example responses can be seen below::
+
+            >>> response_uri = 'https://example.com/callback#access_token=sdlfkj452&state=ss345asyht&token_type=Bearer&scope=hello+world'
+            >>> from oauthlib.oauth2 import MobileApplicationClient
+            >>> client = MobileApplicationClient('your_id')
+            >>> client.parse_request_uri_response(response_uri)
+            {
+                'access_token': 'sdlfkj452',
+                'token_type': 'Bearer',
+                'state': 'ss345asyht',
+                'scope': [u'hello', u'world']
+            }
+            >>> client.parse_request_uri_response(response_uri, state='other')
+            Traceback (most recent call last):
+                File "<stdin>", line 1, in <module>
+                File "oauthlib/oauth2/rfc6749/__init__.py", line 598, in parse_request_uri_response
+                    **scope**
+                File "oauthlib/oauth2/rfc6749/parameters.py", line 197, in parse_implicit_response
+                    raise ValueError("Mismatching or missing state in params.")
+            ValueError: Mismatching or missing state in params.
+            >>> def alert_scope_changed(message, old, new):
+            ...     print(message, old, new)
+            ...
+            >>> oauthlib.signals.scope_changed.connect(alert_scope_changed)
+            >>> client.parse_request_body_response(response_body, scope=['other'])
+            ('Scope has changed from "other" to "hello world".', ['other'], ['hello', 'world'])
+
+        .. _`Section 7.1`: https://tools.ietf.org/html/rfc6749#section-7.1
+        .. _`Section 3.3`: https://tools.ietf.org/html/rfc6749#section-3.3
+        """
+        scope = self.scope if scope is None else scope
+        self.token = parse_implicit_response(uri, state=state, scope=scope)
+        self.populate_token_attributes(self.token)
+        return self.token
diff --git a/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/service_application.py b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/service_application.py
new file mode 100644
index 00000000..8fb17377
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/service_application.py
@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+oauthlib.oauth2.rfc6749
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This module is an implementation of various logic needed
+for consuming and providing OAuth 2.0 RFC6749.
+"""
+import time
+
+from oauthlib.common import to_unicode
+
+from ..parameters import prepare_token_request
+from .base import Client
+
+
+class ServiceApplicationClient(Client):
+    """A public client utilizing the JWT bearer grant.
+
+    JWT bearer tokes can be used to request an access token when a client
+    wishes to utilize an existing trust relationship, expressed through the
+    semantics of (and digital signature or keyed message digest calculated
+    over) the JWT, without a direct user approval step at the authorization
+    server.
+
+    This grant type does not involve an authorization step. It may be
+    used by both public and confidential clients.
+    """
+
+    grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
+
+    def __init__(self, client_id, private_key=None, subject=None, issuer=None,
+                 audience=None, **kwargs):
+        """Initialize a JWT client with defaults for implicit use later.
+
+        :param client_id: Client identifier given by the OAuth provider upon
+                          registration.
+
+        :param private_key: Private key used for signing and encrypting.
+                            Must be given as a string.
+
+        :param subject: The principal that is the subject of the JWT, i.e.
+                        which user is the token requested on behalf of.
+                        For example, ``foo@example.com.
+
+        :param issuer: The JWT MUST contain an "iss" (issuer) claim that
+                       contains a unique identifier for the entity that issued
+                       the JWT. For example, ``your-client@provider.com``.
+
+        :param audience: A value identifying the authorization server as an
+                         intended audience, e.g.
+                         ``https://provider.com/oauth2/token``.
+
+        :param kwargs: Additional arguments to pass to base client, such as
+                       state and token. See ``Client.__init__.__doc__`` for
+                       details.
+        """
+        super().__init__(client_id, **kwargs)
+        self.private_key = private_key
+        self.subject = subject
+        self.issuer = issuer
+        self.audience = audience
+
+    def prepare_request_body(self,
+                             private_key=None,
+                             subject=None,
+                             issuer=None,
+                             audience=None,
+                             expires_at=None,
+                             issued_at=None,
+                             extra_claims=None,
+                             body='',
+                             scope=None,
+                             include_client_id=False,
+                             **kwargs):
+        """Create and add a JWT assertion to the request body.
+
+        :param private_key: Private key used for signing and encrypting.
+                            Must be given as a string.
+
+        :param subject: (sub) The principal that is the subject of the JWT,
+                        i.e.  which user is the token requested on behalf of.
+                        For example, ``foo@example.com.
+
+        :param issuer: (iss) The JWT MUST contain an "iss" (issuer) claim that
+                       contains a unique identifier for the entity that issued
+                       the JWT. For example, ``your-client@provider.com``.
+
+        :param audience: (aud) A value identifying the authorization server as an
+                         intended audience, e.g.
+                         ``https://provider.com/oauth2/token``.
+
+        :param expires_at: A unix expiration timestamp for the JWT. Defaults
+                           to an hour from now, i.e. ``time.time() + 3600``.
+
+        :param issued_at: A unix timestamp of when the JWT was created.
+                          Defaults to now, i.e. ``time.time()``.
+
+        :param extra_claims: A dict of additional claims to include in the JWT.
+
+        :param body: Existing request body (URL encoded string) to embed parameters
+                     into. This may contain extra parameters. Default ''.
+
+        :param scope: The scope of the access request.
+
+        :param include_client_id: `True` to send the `client_id` in the
+                                  body of the upstream request. This is required
+                                  if the client is not authenticating with the
+                                  authorization server as described in
+                                  `Section 3.2.1`_. False otherwise (default).
+        :type include_client_id: Boolean
+
+        :param not_before: A unix timestamp after which the JWT may be used.
+                           Not included unless provided. *
+
+        :param jwt_id: A unique JWT token identifier. Not included unless
+                       provided. *
+
+        :param kwargs: Extra credentials to include in the token request.
+
+        Parameters marked with a `*` above are not explicit arguments in the
+        function signature, but are specially documented arguments for items
+        appearing in the generic `**kwargs` keyworded input.
+
+        The "scope" parameter may be used, as defined in the Assertion
+        Framework for OAuth 2.0 Client Authentication and Authorization Grants
+        [I-D.ietf-oauth-assertions] specification, to indicate the requested
+        scope.
+
+        Authentication of the client is optional, as described in
+        `Section 3.2.1`_ of OAuth 2.0 [RFC6749] and consequently, the
+        "client_id" is only needed when a form of client authentication that
+        relies on the parameter is used.
+
+        The following non-normative example demonstrates an Access Token
+        Request with a JWT as an authorization grant (with extra line breaks
+        for display purposes only):
+
+        .. code-block: http
+
+            POST /token.oauth2 HTTP/1.1
+            Host: as.example.com
+            Content-Type: application/x-www-form-urlencoded
+
+            grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer
+            &assertion=eyJhbGciOiJFUzI1NiJ9.
+            eyJpc3Mi[...omitted for brevity...].
+            J9l-ZhwP[...omitted for brevity...]
+
+        .. _`Section 3.2.1`: https://tools.ietf.org/html/rfc6749#section-3.2.1
+        """
+        import jwt
+
+        key = private_key or self.private_key
+        if not key:
+            raise ValueError('An encryption key must be supplied to make JWT'
+                             ' token requests.')
+        claim = {
+            'iss': issuer or self.issuer,
+            'aud': audience or self.audience,
+            'sub': subject or self.subject,
+            'exp': int(expires_at or time.time() + 3600),
+            'iat': int(issued_at or time.time()),
+        }
+
+        for attr in ('iss', 'aud', 'sub'):
+            if claim[attr] is None:
+                raise ValueError(
+                        'Claim must include %s but none was given.' % attr)
+
+        if 'not_before' in kwargs:
+            claim['nbf'] = kwargs.pop('not_before')
+
+        if 'jwt_id' in kwargs:
+            claim['jti'] = kwargs.pop('jwt_id')
+
+        claim.update(extra_claims or {})
+
+        assertion = jwt.encode(claim, key, 'RS256')
+        assertion = to_unicode(assertion)
+
+        kwargs['client_id'] = self.client_id
+        kwargs['include_client_id'] = include_client_id
+        scope = self.scope if scope is None else scope
+        return prepare_token_request(self.grant_type,
+                                     body=body,
+                                     assertion=assertion,
+                                     scope=scope,
+                                     **kwargs)
diff --git a/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/web_application.py b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/web_application.py
new file mode 100644
index 00000000..50890fbf
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/web_application.py
@@ -0,0 +1,222 @@
+# -*- coding: utf-8 -*-
+"""
+oauthlib.oauth2.rfc6749
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This module is an implementation of various logic needed
+for consuming and providing OAuth 2.0 RFC6749.
+"""
+import warnings
+
+from ..parameters import (
+    parse_authorization_code_response, prepare_grant_uri,
+    prepare_token_request,
+)
+from .base import Client
+
+
+class WebApplicationClient(Client):
+
+    """A client utilizing the authorization code grant workflow.
+
+    A web application is a confidential client running on a web
+    server.  Resource owners access the client via an HTML user
+    interface rendered in a user-agent on the device used by the
+    resource owner.  The client credentials as well as any access
+    token issued to the client are stored on the web server and are
+    not exposed to or accessible by the resource owner.
+
+    The authorization code grant type is used to obtain both access
+    tokens and refresh tokens and is optimized for confidential clients.
+    As a redirection-based flow, the client must be capable of
+    interacting with the resource owner's user-agent (typically a web
+    browser) and capable of receiving incoming requests (via redirection)
+    from the authorization server.
+    """
+    
+    grant_type = 'authorization_code'
+
+    def __init__(self, client_id, code=None, **kwargs):
+        super().__init__(client_id, **kwargs)
+        self.code = code
+
+    def prepare_request_uri(self, uri, redirect_uri=None, scope=None,
+                            state=None, code_challenge=None, code_challenge_method='plain', **kwargs):
+        """Prepare the authorization code request URI
+
+        The client constructs the request URI by adding the following
+        parameters to the query component of the authorization endpoint URI
+        using the "application/x-www-form-urlencoded" format, per `Appendix B`_:
+
+        :param redirect_uri:  OPTIONAL. The redirect URI must be an absolute URI
+                              and it should have been registered with the OAuth
+                              provider prior to use. As described in `Section 3.1.2`_.
+
+        :param scope:  OPTIONAL. The scope of the access request as described by
+                       Section 3.3`_. These may be any string but are commonly
+                       URIs or various categories such as ``videos`` or ``documents``.
+
+        :param state:   RECOMMENDED.  An opaque value used by the client to maintain
+                        state between the request and callback.  The authorization
+                        server includes this value when redirecting the user-agent back
+                        to the client.  The parameter SHOULD be used for preventing
+                        cross-site request forgery as described in `Section 10.12`_.
+
+        :param code_challenge: OPTIONAL. PKCE parameter. REQUIRED if PKCE is enforced. 
+                        A challenge derived from the code_verifier that is sent in the 
+                        authorization request, to be verified against later.
+
+        :param code_challenge_method: OPTIONAL. PKCE parameter. A method that was used to derive code challenge.
+                                      Defaults to "plain" if not present in the request.
+
+        :param kwargs:  Extra arguments to include in the request URI.
+
+        In addition to supplied parameters, OAuthLib will append the ``client_id``
+        that was provided in the constructor as well as the mandatory ``response_type``
+        argument, set to ``code``::
+
+            >>> from oauthlib.oauth2 import WebApplicationClient
+            >>> client = WebApplicationClient('your_id')
+            >>> client.prepare_request_uri('https://example.com')
+            'https://example.com?client_id=your_id&response_type=code'
+            >>> client.prepare_request_uri('https://example.com', redirect_uri='https://a.b/callback')
+            'https://example.com?client_id=your_id&response_type=code&redirect_uri=https%3A%2F%2Fa.b%2Fcallback'
+            >>> client.prepare_request_uri('https://example.com', scope=['profile', 'pictures'])
+            'https://example.com?client_id=your_id&response_type=code&scope=profile+pictures'
+            >>> client.prepare_request_uri('https://example.com', code_challenge='kjasBS523KdkAILD2k78NdcJSk2k3KHG6')
+            'https://example.com?client_id=your_id&response_type=code&code_challenge=kjasBS523KdkAILD2k78NdcJSk2k3KHG6'
+            >>> client.prepare_request_uri('https://example.com', code_challenge_method='S256')
+            'https://example.com?client_id=your_id&response_type=code&code_challenge_method=S256'
+            >>> client.prepare_request_uri('https://example.com', foo='bar')
+            'https://example.com?client_id=your_id&response_type=code&foo=bar'
+
+        .. _`Appendix B`: https://tools.ietf.org/html/rfc6749#appendix-B
+        .. _`Section 2.2`: https://tools.ietf.org/html/rfc6749#section-2.2
+        .. _`Section 3.1.2`: https://tools.ietf.org/html/rfc6749#section-3.1.2
+        .. _`Section 3.3`: https://tools.ietf.org/html/rfc6749#section-3.3
+        .. _`Section 10.12`: https://tools.ietf.org/html/rfc6749#section-10.12
+        """
+        scope = self.scope if scope is None else scope
+        return prepare_grant_uri(uri, self.client_id, 'code',
+                                 redirect_uri=redirect_uri, scope=scope, state=state, code_challenge=code_challenge,
+                                 code_challenge_method=code_challenge_method, **kwargs)
+
+    def prepare_request_body(self, code=None, redirect_uri=None, body='',
+                             include_client_id=True, code_verifier=None, **kwargs):
+        """Prepare the access token request body.
+
+        The client makes a request to the token endpoint by adding the
+        following parameters using the "application/x-www-form-urlencoded"
+        format in the HTTP request entity-body:
+
+        :param code:    REQUIRED. The authorization code received from the
+                        authorization server.
+
+        :param redirect_uri:    REQUIRED, if the "redirect_uri" parameter was included in the
+                                authorization request as described in `Section 4.1.1`_, and their
+                                values MUST be identical.
+
+        :param body: Existing request body (URL encoded string) to embed parameters
+                     into. This may contain extra parameters. Default ''.
+
+        :param include_client_id: `True` (default) to send the `client_id` in the
+                                  body of the upstream request. This is required
+                                  if the client is not authenticating with the
+                                  authorization server as described in `Section 3.2.1`_.
+        :type include_client_id: Boolean
+
+        :param code_verifier: OPTIONAL. A cryptographically random string that is used to correlate the
+                                        authorization request to the token request.
+
+        :param kwargs: Extra parameters to include in the token request.
+
+        In addition OAuthLib will add the ``grant_type`` parameter set to
+        ``authorization_code``.
+
+        If the client type is confidential or the client was issued client
+        credentials (or assigned other authentication requirements), the
+        client MUST authenticate with the authorization server as described
+        in `Section 3.2.1`_::
+
+            >>> from oauthlib.oauth2 import WebApplicationClient
+            >>> client = WebApplicationClient('your_id')
+            >>> client.prepare_request_body(code='sh35ksdf09sf')
+            'grant_type=authorization_code&code=sh35ksdf09sf'
+            >>> client.prepare_request_body(code_verifier='KB46DCKJ873NCGXK5GD682NHDKK34GR')
+            'grant_type=authorization_code&code_verifier=KB46DCKJ873NCGXK5GD682NHDKK34GR'
+            >>> client.prepare_request_body(code='sh35ksdf09sf', foo='bar')
+            'grant_type=authorization_code&code=sh35ksdf09sf&foo=bar'
+
+        `Section 3.2.1` also states:
+            In the "authorization_code" "grant_type" request to the token
+            endpoint, an unauthenticated client MUST send its "client_id" to
+            prevent itself from inadvertently accepting a code intended for a
+            client with a different "client_id".  This protects the client from
+            substitution of the authentication code.  (It provides no additional
+            security for the protected resource.)
+
+        .. _`Section 4.1.1`: https://tools.ietf.org/html/rfc6749#section-4.1.1
+        .. _`Section 3.2.1`: https://tools.ietf.org/html/rfc6749#section-3.2.1
+        """
+        code = code or self.code
+        if 'client_id' in kwargs:
+            warnings.warn("`client_id` has been deprecated in favor of "
+                          "`include_client_id`, a boolean value which will "
+                          "include the already configured `self.client_id`.",
+                          DeprecationWarning)
+            if kwargs['client_id'] != self.client_id:
+                raise ValueError("`client_id` was supplied as an argument, but "
+                                 "it does not match `self.client_id`")
+
+        kwargs['client_id'] = self.client_id
+        kwargs['include_client_id'] = include_client_id
+        return prepare_token_request(self.grant_type, code=code, body=body,
+                                     redirect_uri=redirect_uri, code_verifier=code_verifier, **kwargs)
+
+    def parse_request_uri_response(self, uri, state=None):
+        """Parse the URI query for code and state.
+
+        If the resource owner grants the access request, the authorization
+        server issues an authorization code and delivers it to the client by
+        adding the following parameters to the query component of the
+        redirection URI using the "application/x-www-form-urlencoded" format:
+
+        :param uri: The callback URI that resulted from the user being redirected
+                    back from the provider to you, the client.
+        :param state: The state provided in the authorization request.
+
+        **code**
+            The authorization code generated by the authorization server.
+            The authorization code MUST expire shortly after it is issued
+            to mitigate the risk of leaks. A maximum authorization code
+            lifetime of 10 minutes is RECOMMENDED. The client MUST NOT
+            use the authorization code more than once. If an authorization
+            code is used more than once, the authorization server MUST deny
+            the request and SHOULD revoke (when possible) all tokens
+            previously issued based on that authorization code.
+            The authorization code is bound to the client identifier and
+            redirection URI.
+
+        **state**
+                If the "state" parameter was present in the authorization request.
+
+        This method is mainly intended to enforce strict state checking with
+        the added benefit of easily extracting parameters from the URI::
+
+            >>> from oauthlib.oauth2 import WebApplicationClient
+            >>> client = WebApplicationClient('your_id')
+            >>> uri = 'https://example.com/callback?code=sdfkjh345&state=sfetw45'
+            >>> client.parse_request_uri_response(uri, state='sfetw45')
+            {'state': 'sfetw45', 'code': 'sdfkjh345'}
+            >>> client.parse_request_uri_response(uri, state='other')
+            Traceback (most recent call last):
+                File "<stdin>", line 1, in <module>
+                File "oauthlib/oauth2/rfc6749/__init__.py", line 357, in parse_request_uri_response
+                    back from the provider to you, the client.
+                File "oauthlib/oauth2/rfc6749/parameters.py", line 153, in parse_authorization_code_response
+                    raise MismatchingStateError()
+            oauthlib.oauth2.rfc6749.errors.MismatchingStateError
+        """
+        response = parse_authorization_code_response(uri, state=state)
+        self.populate_code_attributes(response)
+        return response