File manager - Edit - /home/newsbmcs.com/public_html/static/img/logo/rfc6749.tar
Back
request_validator.py 0000644 00000070263 15030301546 0010660 0 ustar 00 """ oauthlib.oauth2.rfc6749.request_validator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ """ import logging log = logging.getLogger(__name__) class RequestValidator: def client_authentication_required(self, request, *args, **kwargs): """Determine if client authentication is required for current request. According to the rfc6749, client authentication is required in the following cases: - Resource Owner Password Credentials Grant, when Client type is Confidential or when Client was issued client credentials or whenever Client provided client authentication, see `Section 4.3.2`_. - Authorization Code Grant, when Client type is Confidential or when Client was issued client credentials or whenever Client provided client authentication, see `Section 4.1.3`_. - Refresh Token Grant, when Client type is Confidential or when Client was issued client credentials or whenever Client provided client authentication, see `Section 6`_ :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant - Resource Owner Password Credentials Grant - Refresh Token Grant .. _`Section 4.3.2`: https://tools.ietf.org/html/rfc6749#section-4.3.2 .. _`Section 4.1.3`: https://tools.ietf.org/html/rfc6749#section-4.1.3 .. _`Section 6`: https://tools.ietf.org/html/rfc6749#section-6 """ return True def authenticate_client(self, request, *args, **kwargs): """Authenticate client through means outside the OAuth 2 spec. Means of authentication is negotiated beforehand and may for example be `HTTP Basic Authentication Scheme`_ which utilizes the Authorization header. Headers may be accesses through request.headers and parameters found in both body and query can be obtained by direct attribute access, i.e. request.client_id for client_id in the URL query. The authentication process is required to contain the identification of the client (i.e. search the database based on the client_id). In case the client doesn't exist based on the received client_id, this method has to return False and the HTTP response created by the library will contain 'invalid_client' message. After the client identification succeeds, this method needs to set the client on the request, i.e. request.client = client. A client object's class must contain the 'client_id' attribute and the 'client_id' must have a value. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant - Resource Owner Password Credentials Grant (may be disabled) - Client Credentials Grant - Refresh Token Grant .. _`HTTP Basic Authentication Scheme`: https://tools.ietf.org/html/rfc1945#section-11.1 """ raise NotImplementedError('Subclasses must implement this method.') def authenticate_client_id(self, client_id, request, *args, **kwargs): """Ensure client_id belong to a non-confidential client. A non-confidential client is one that is not required to authenticate through other means, such as using HTTP Basic. Note, while not strictly necessary it can often be very convenient to set request.client to the client object associated with the given client_id. :param client_id: Unicode client identifier. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant """ raise NotImplementedError('Subclasses must implement this method.') def confirm_redirect_uri(self, client_id, code, redirect_uri, client, request, *args, **kwargs): """Ensure that the authorization process represented by this authorization code began with this 'redirect_uri'. If the client specifies a redirect_uri when obtaining code then that redirect URI must be bound to the code and verified equal in this method, according to RFC 6749 section 4.1.3. Do not compare against the client's allowed redirect URIs, but against the URI used when the code was saved. :param client_id: Unicode client identifier. :param code: Unicode authorization_code. :param redirect_uri: Unicode absolute URI. :param client: Client object set by you, see ``.authenticate_client``. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant (during token request) """ raise NotImplementedError('Subclasses must implement this method.') def get_default_redirect_uri(self, client_id, request, *args, **kwargs): """Get the default redirect URI for the client. :param client_id: Unicode client identifier. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: The default redirect URI for the client Method is used by: - Authorization Code Grant - Implicit Grant """ raise NotImplementedError('Subclasses must implement this method.') def get_default_scopes(self, client_id, request, *args, **kwargs): """Get the default scopes for the client. :param client_id: Unicode client identifier. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: List of default scopes Method is used by all core grant types: - Authorization Code Grant - Implicit Grant - Resource Owner Password Credentials Grant - Client Credentials grant """ raise NotImplementedError('Subclasses must implement this method.') def get_original_scopes(self, refresh_token, request, *args, **kwargs): """Get the list of scopes associated with the refresh token. :param refresh_token: Unicode refresh token. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: List of scopes. Method is used by: - Refresh token grant """ raise NotImplementedError('Subclasses must implement this method.') def is_within_original_scope(self, request_scopes, refresh_token, request, *args, **kwargs): """Check if requested scopes are within a scope of the refresh token. When access tokens are refreshed the scope of the new token needs to be within the scope of the original token. This is ensured by checking that all requested scopes strings are on the list returned by the get_original_scopes. If this check fails, is_within_original_scope is called. The method can be used in situations where returning all valid scopes from the get_original_scopes is not practical. :param request_scopes: A list of scopes that were requested by client. :param refresh_token: Unicode refresh_token. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Refresh token grant """ return False def introspect_token(self, token, token_type_hint, request, *args, **kwargs): """Introspect an access or refresh token. Called once the introspect request is validated. This method should verify the *token* and either return a dictionary with the list of claims associated, or `None` in case the token is unknown. Below the list of registered claims you should be interested in: - scope : space-separated list of scopes - client_id : client identifier - username : human-readable identifier for the resource owner - token_type : type of the token - exp : integer timestamp indicating when this token will expire - iat : integer timestamp indicating when this token was issued - nbf : integer timestamp indicating when it can be "not-before" used - sub : subject of the token - identifier of the resource owner - aud : list of string identifiers representing the intended audience - iss : string representing issuer of this token - jti : string identifier for the token Note that most of them are coming directly from JWT RFC. More details can be found in `Introspect Claims`_ or `JWT Claims`_. The implementation can use *token_type_hint* to improve lookup efficiency, but must fallback to other types to be compliant with RFC. The dict of claims is added to request.token after this method. :param token: The token string. :param token_type_hint: access_token or refresh_token. :param request: OAuthlib request. :type request: oauthlib.common.Request Method is used by: - Introspect Endpoint (all grants are compatible) .. _`Introspect Claims`: https://tools.ietf.org/html/rfc7662#section-2.2 .. _`JWT Claims`: https://tools.ietf.org/html/rfc7519#section-4 """ raise NotImplementedError('Subclasses must implement this method.') def invalidate_authorization_code(self, client_id, code, request, *args, **kwargs): """Invalidate an authorization code after use. :param client_id: Unicode client identifier. :param code: The authorization code grant (request.code). :param request: OAuthlib request. :type request: oauthlib.common.Request Method is used by: - Authorization Code Grant """ raise NotImplementedError('Subclasses must implement this method.') def revoke_token(self, token, token_type_hint, request, *args, **kwargs): """Revoke an access or refresh token. :param token: The token string. :param token_type_hint: access_token or refresh_token. :param request: OAuthlib request. :type request: oauthlib.common.Request Method is used by: - Revocation Endpoint """ raise NotImplementedError('Subclasses must implement this method.') def rotate_refresh_token(self, request): """Determine whether to rotate the refresh token. Default, yes. When access tokens are refreshed the old refresh token can be kept or replaced with a new one (rotated). Return True to rotate and and False for keeping original. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Refresh Token Grant """ return True def save_authorization_code(self, client_id, code, request, *args, **kwargs): """Persist the authorization_code. The code should at minimum be stored with: - the client_id (``client_id``) - the redirect URI used (``request.redirect_uri``) - a resource owner / user (``request.user``) - the authorized scopes (``request.scopes``) To support PKCE, you MUST associate the code with: - Code Challenge (``request.code_challenge``) and - Code Challenge Method (``request.code_challenge_method``) To support OIDC, you MUST associate the code with: - nonce, if present (``code["nonce"]``) The ``code`` argument is actually a dictionary, containing at least a ``code`` key with the actual authorization code: ``{'code': 'sdf345jsdf0934f'}`` It may also have a ``claims`` parameter which, when present, will be a dict deserialized from JSON as described at http://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter This value should be saved in this method and used again in ``.validate_code``. :param client_id: Unicode client identifier. :param code: A dict of the authorization code grant and, optionally, state. :param request: OAuthlib request. :type request: oauthlib.common.Request Method is used by: - Authorization Code Grant """ raise NotImplementedError('Subclasses must implement this method.') def save_token(self, token, request, *args, **kwargs): """Persist the token with a token type specific method. Currently, only save_bearer_token is supported. :param token: A (Bearer) token dict. :param request: OAuthlib request. :type request: oauthlib.common.Request """ return self.save_bearer_token(token, request, *args, **kwargs) def save_bearer_token(self, token, request, *args, **kwargs): """Persist the Bearer token. The Bearer token should at minimum be associated with: - a client and it's client_id, if available - a resource owner / user (request.user) - authorized scopes (request.scopes) - an expiration time - a refresh token, if issued - a claims document, if present in request.claims The Bearer token dict may hold a number of items:: { 'token_type': 'Bearer', 'access_token': 'askfjh234as9sd8', 'expires_in': 3600, 'scope': 'string of space separated authorized scopes', 'refresh_token': '23sdf876234', # if issued 'state': 'given_by_client', # if supplied by client (implicit ONLY) } Note that while "scope" is a string-separated list of authorized scopes, the original list is still available in request.scopes. The token dict is passed as a reference so any changes made to the dictionary will go back to the user. If additional information must return to the client user, and it is only possible to get this information after writing the token to storage, it should be added to the token dictionary. If the token dictionary must be modified but the changes should not go back to the user, a copy of the dictionary must be made before making the changes. Also note that if an Authorization Code grant request included a valid claims parameter (for OpenID Connect) then the request.claims property will contain the claims dict, which should be saved for later use when generating the id_token and/or UserInfo response content. :param token: A Bearer token dict. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: The default redirect URI for the client Method is used by all core grant types issuing Bearer tokens: - Authorization Code Grant - Implicit Grant - Resource Owner Password Credentials Grant (might not associate a client) - Client Credentials grant """ raise NotImplementedError('Subclasses must implement this method.') def validate_bearer_token(self, token, scopes, request): """Ensure the Bearer token is valid and authorized access to scopes. :param token: A string of random characters. :param scopes: A list of scopes associated with the protected resource. :param request: OAuthlib request. :type request: oauthlib.common.Request A key to OAuth 2 security and restricting impact of leaked tokens is the short expiration time of tokens, *always ensure the token has not expired!*. Two different approaches to scope validation: 1) all(scopes). The token must be authorized access to all scopes associated with the resource. For example, the token has access to ``read-only`` and ``images``, thus the client can view images but not upload new. Allows for fine grained access control through combining various scopes. 2) any(scopes). The token must be authorized access to one of the scopes associated with the resource. For example, token has access to ``read-only-images``. Allows for fine grained, although arguably less convenient, access control. A powerful way to use scopes would mimic UNIX ACLs and see a scope as a group with certain privileges. For a restful API these might map to HTTP verbs instead of read, write and execute. Note, the request.user attribute can be set to the resource owner associated with this token. Similarly the request.client and request.scopes attribute can be set to associated client object and authorized scopes. If you then use a decorator such as the one provided for django these attributes will be made available in all protected views as keyword arguments. :param token: Unicode Bearer token :param scopes: List of scopes (defined by you) :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is indirectly used by all core Bearer token issuing grant types: - Authorization Code Grant - Implicit Grant - Resource Owner Password Credentials Grant - Client Credentials Grant """ raise NotImplementedError('Subclasses must implement this method.') def validate_client_id(self, client_id, request, *args, **kwargs): """Ensure client_id belong to a valid and active client. Note, while not strictly necessary it can often be very convenient to set request.client to the client object associated with the given client_id. :param client_id: Unicode client identifier. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant - Implicit Grant """ raise NotImplementedError('Subclasses must implement this method.') def validate_code(self, client_id, code, client, request, *args, **kwargs): """Verify that the authorization_code is valid and assigned to the given client. Before returning true, set the following based on the information stored with the code in 'save_authorization_code': - request.user - request.scopes - request.claims (if given) OBS! The request.user attribute should be set to the resource owner associated with this authorization code. Similarly request.scopes must also be set. The request.claims property, if it was given, should assigned a dict. If PKCE is enabled (see 'is_pkce_required' and 'save_authorization_code') you MUST set the following based on the information stored: - request.code_challenge - request.code_challenge_method :param client_id: Unicode client identifier. :param code: Unicode authorization code. :param client: Client object set by you, see ``.authenticate_client``. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant """ raise NotImplementedError('Subclasses must implement this method.') def validate_grant_type(self, client_id, grant_type, client, request, *args, **kwargs): """Ensure client is authorized to use the grant_type requested. :param client_id: Unicode client identifier. :param grant_type: Unicode grant type, i.e. authorization_code, password. :param client: Client object set by you, see ``.authenticate_client``. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant - Resource Owner Password Credentials Grant - Client Credentials Grant - Refresh Token Grant """ raise NotImplementedError('Subclasses must implement this method.') def validate_redirect_uri(self, client_id, redirect_uri, request, *args, **kwargs): """Ensure client is authorized to redirect to the redirect_uri requested. All clients should register the absolute URIs of all URIs they intend to redirect to. The registration is outside of the scope of oauthlib. :param client_id: Unicode client identifier. :param redirect_uri: Unicode absolute URI. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant - Implicit Grant """ raise NotImplementedError('Subclasses must implement this method.') def validate_refresh_token(self, refresh_token, client, request, *args, **kwargs): """Ensure the Bearer token is valid and authorized access to scopes. OBS! The request.user attribute should be set to the resource owner associated with this refresh token. :param refresh_token: Unicode refresh token. :param client: Client object set by you, see ``.authenticate_client``. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant (indirectly by issuing refresh tokens) - Resource Owner Password Credentials Grant (also indirectly) - Refresh Token Grant """ raise NotImplementedError('Subclasses must implement this method.') def validate_response_type(self, client_id, response_type, client, request, *args, **kwargs): """Ensure client is authorized to use the response_type requested. :param client_id: Unicode client identifier. :param response_type: Unicode response type, i.e. code, token. :param client: Client object set by you, see ``.authenticate_client``. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant - Implicit Grant """ raise NotImplementedError('Subclasses must implement this method.') def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs): """Ensure the client is authorized access to requested scopes. :param client_id: Unicode client identifier. :param scopes: List of scopes (defined by you). :param client: Client object set by you, see ``.authenticate_client``. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by all core grant types: - Authorization Code Grant - Implicit Grant - Resource Owner Password Credentials Grant - Client Credentials Grant """ raise NotImplementedError('Subclasses must implement this method.') def validate_user(self, username, password, client, request, *args, **kwargs): """Ensure the username and password is valid. OBS! The validation should also set the user attribute of the request to a valid resource owner, i.e. request.user = username or similar. If not set you will be unable to associate a token with a user in the persistence method used (commonly, save_bearer_token). :param username: Unicode username. :param password: Unicode password. :param client: Client object set by you, see ``.authenticate_client``. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Resource Owner Password Credentials Grant """ raise NotImplementedError('Subclasses must implement this method.') def is_pkce_required(self, client_id, request): """Determine if current request requires PKCE. Default, False. This is called for both "authorization" and "token" requests. Override this method by ``return True`` to enable PKCE for everyone. You might want to enable it only for public clients. Note that PKCE can also be used in addition of a client authentication. OAuth 2.0 public clients utilizing the Authorization Code Grant are susceptible to the authorization code interception attack. This specification describes the attack as well as a technique to mitigate against the threat through the use of Proof Key for Code Exchange (PKCE, pronounced "pixy"). See `RFC7636`_. :param client_id: Client identifier. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: True or False Method is used by: - Authorization Code Grant .. _`RFC7636`: https://tools.ietf.org/html/rfc7636 """ return False def get_code_challenge(self, code, request): """Is called for every "token" requests. When the server issues the authorization code in the authorization response, it MUST associate the ``code_challenge`` and ``code_challenge_method`` values with the authorization code so it can be verified later. Typically, the ``code_challenge`` and ``code_challenge_method`` values are stored in encrypted form in the ``code`` itself but could alternatively be stored on the server associated with the code. The server MUST NOT include the ``code_challenge`` value in client requests in a form that other entities can extract. Return the ``code_challenge`` associated to the code. If ``None`` is returned, code is considered to not be associated to any challenges. :param code: Authorization code. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: code_challenge string Method is used by: - Authorization Code Grant - when PKCE is active """ return None def get_code_challenge_method(self, code, request): """Is called during the "token" request processing, when a ``code_verifier`` and a ``code_challenge`` has been provided. See ``.get_code_challenge``. Must return ``plain`` or ``S256``. You can return a custom value if you have implemented your own ``AuthorizationCodeGrant`` class. :param code: Authorization code. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: code_challenge_method string Method is used by: - Authorization Code Grant - when PKCE is active """ raise NotImplementedError('Subclasses must implement this method.') def is_origin_allowed(self, client_id, origin, request, *args, **kwargs): """Indicate if the given origin is allowed to access the token endpoint via Cross-Origin Resource Sharing (CORS). CORS is used by browser-based clients, such as Single-Page Applications, to perform the Authorization Code Grant. (Note: If performing Authorization Code Grant via a public client such as a browser, you should use PKCE as well.) If this method returns true, the appropriate CORS headers will be added to the response. By default this method always returns False, meaning CORS is disabled. :param client_id: Unicode client identifier. :param redirect_uri: Unicode origin. :param request: OAuthlib request. :type request: oauthlib.common.Request :rtype: bool Method is used by: - Authorization Code Grant - Refresh Token Grant """ return False clients/base.py 0000644 00000064034 15030301546 0007475 0 ustar 00 # -*- 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') clients/__pycache__/__init__.cpython-310.pyc 0000644 00000001371 15030301546 0014654 0 ustar 00 o �h� � @ s\ d Z ddlmZ ddlmZmZmZmZ ddlm Z ddl mZ ddlm Z ddlmZ dS ) z� oauthlib.oauth2.rfc6749 ~~~~~~~~~~~~~~~~~~~~~~~ This module is an implementation of various logic needed for consuming OAuth 2.0 RFC6749. � )�BackendApplicationClient)�AUTH_HEADER�BODY� URI_QUERY�Client)�LegacyApplicationClient)�MobileApplicationClient)�ServiceApplicationClient)�WebApplicationClientN)�__doc__�backend_applicationr �baser r r r �legacy_applicationr �mobile_applicationr �service_applicationr �web_applicationr � r r �[/usr/local/CyberCP/lib/python3.10/site-packages/oauthlib/oauth2/rfc6749/clients/__init__.py�<module> s clients/__pycache__/service_application.cpython-310.pyc 0000644 00000016121 15030301546 0017137 0 ustar 00 o �h� � @ sD d Z ddlZddlmZ ddlmZ ddlmZ G dd � d e�ZdS ) z� oauthlib.oauth2.rfc6749 ~~~~~~~~~~~~~~~~~~~~~~~ This module is an implementation of various logic needed for consuming and providing OAuth 2.0 RFC6749. � N)� to_unicode� )�prepare_token_request� )�Clientc sH e Zd ZdZdZ d � fdd� Z ddd �Z� ZS )�ServiceApplicationClienta� 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. z+urn:ietf:params:oauth:grant-type:jwt-bearerNc s0 t � j|fi |�� || _|| _|| _|| _dS )ad 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. N)�super�__init__�private_key�subject�issuer�audience)�self� client_idr r r r �kwargs�� __class__� �f/usr/local/CyberCP/lib/python3.10/site-packages/oauthlib/oauth2/rfc6749/clients/service_application.pyr s z!ServiceApplicationClient.__init__� Fc K s ddl }|p| j} | std��|p| j|p| j|p| jt|p#t�� d �t|p*t�� �d�}dD ]}|| du r>td| ��q0d|v rJ|�d�|d <