Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
request_validator.py681 linesDownload Raw Back to rfc6749
1"""2oauthlib.oauth2.rfc6749.request_validator3~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~4"""5import logging6 7log = logging.getLogger(__name__)8 9 10class RequestValidator:11 12    def client_authentication_required(self, request, *args, **kwargs):13        """Determine if client authentication is required for current request.14 15        According to the rfc6749, client authentication is required in the following cases:16            - Resource Owner Password Credentials Grant, when Client type is Confidential or when17              Client was issued client credentials or whenever Client provided client18              authentication, see `Section 4.3.2`_.19            - Authorization Code Grant, when Client type is Confidential or when Client was issued20              client credentials or whenever Client provided client authentication,21              see `Section 4.1.3`_.22            - Refresh Token Grant, when Client type is Confidential or when Client was issued23              client credentials or whenever Client provided client authentication, see24              `Section 6`_25 26        :param request: OAuthlib request.27        :type request: oauthlib.common.Request28        :rtype: True or False29 30        Method is used by:31            - Authorization Code Grant32            - Resource Owner Password Credentials Grant33            - Refresh Token Grant34 35        .. _`Section 4.3.2`: https://tools.ietf.org/html/rfc6749#section-4.3.236        .. _`Section 4.1.3`: https://tools.ietf.org/html/rfc6749#section-4.1.337        .. _`Section 6`: https://tools.ietf.org/html/rfc6749#section-638        """39        return True40 41    def authenticate_client(self, request, *args, **kwargs):42        """Authenticate client through means outside the OAuth 2 spec.43 44        Means of authentication is negotiated beforehand and may for example45        be `HTTP Basic Authentication Scheme`_ which utilizes the Authorization46        header.47 48        Headers may be accesses through request.headers and parameters found in49        both body and query can be obtained by direct attribute access, i.e.50        request.client_id for client_id in the URL query.51		52        The authentication process is required to contain the identification of53        the client (i.e. search the database based on the client_id). In case the54        client doesn't exist based on the received client_id, this method has to55        return False and the HTTP response created by the library will contain56        'invalid_client' message. 57 58        After the client identification succeeds, this method needs to set the59        client on the request, i.e. request.client = client. A client object's60        class must contain the 'client_id' attribute and the 'client_id' must have61        a value.62 63        :param request: OAuthlib request.64        :type request: oauthlib.common.Request65        :rtype: True or False66 67        Method is used by:68            - Authorization Code Grant69            - Resource Owner Password Credentials Grant (may be disabled)70            - Client Credentials Grant71            - Refresh Token Grant72 73        .. _`HTTP Basic Authentication Scheme`: https://tools.ietf.org/html/rfc1945#section-11.174        """75        raise NotImplementedError('Subclasses must implement this method.')76 77    def authenticate_client_id(self, client_id, request, *args, **kwargs):78        """Ensure client_id belong to a non-confidential client.79 80        A non-confidential client is one that is not required to authenticate81        through other means, such as using HTTP Basic.82 83        Note, while not strictly necessary it can often be very convenient84        to set request.client to the client object associated with the85        given client_id.86 87        :param client_id: Unicode client identifier.88        :param request: OAuthlib request.89        :type request: oauthlib.common.Request90        :rtype: True or False91 92        Method is used by:93            - Authorization Code Grant94        """95        raise NotImplementedError('Subclasses must implement this method.')96 97    def confirm_redirect_uri(self, client_id, code, redirect_uri, client, request,98                             *args, **kwargs):99        """Ensure that the authorization process represented by this authorization100        code began with this 'redirect_uri'.101 102        If the client specifies a redirect_uri when obtaining code then that103        redirect URI must be bound to the code and verified equal in this104        method, according to RFC 6749 section 4.1.3.  Do not compare against105        the client's allowed redirect URIs, but against the URI used when the106        code was saved.107 108        :param client_id: Unicode client identifier.109        :param code: Unicode authorization_code.110        :param redirect_uri: Unicode absolute URI.111        :param client: Client object set by you, see ``.authenticate_client``.112        :param request: OAuthlib request.113        :type request: oauthlib.common.Request114        :rtype: True or False115 116        Method is used by:117            - Authorization Code Grant (during token request)118        """119        raise NotImplementedError('Subclasses must implement this method.')120 121    def get_default_redirect_uri(self, client_id, request, *args, **kwargs):122        """Get the default redirect URI for the client.123 124        :param client_id: Unicode client identifier.125        :param request: OAuthlib request.126        :type request: oauthlib.common.Request127        :rtype: The default redirect URI for the client128 129        Method is used by:130            - Authorization Code Grant131            - Implicit Grant132        """133        raise NotImplementedError('Subclasses must implement this method.')134 135    def get_default_scopes(self, client_id, request, *args, **kwargs):136        """Get the default scopes for the client.137 138        :param client_id: Unicode client identifier.139        :param request: OAuthlib request.140        :type request: oauthlib.common.Request141        :rtype: List of default scopes142 143        Method is used by all core grant types:144            - Authorization Code Grant145            - Implicit Grant146            - Resource Owner Password Credentials Grant147            - Client Credentials grant148        """149        raise NotImplementedError('Subclasses must implement this method.')150 151    def get_original_scopes(self, refresh_token, request, *args, **kwargs):152        """Get the list of scopes associated with the refresh token.153 154        :param refresh_token: Unicode refresh token.155        :param request: OAuthlib request.156        :type request: oauthlib.common.Request157        :rtype: List of scopes.158 159        Method is used by:160            - Refresh token grant161        """162        raise NotImplementedError('Subclasses must implement this method.')163 164    def is_within_original_scope(self, request_scopes, refresh_token, request, *args, **kwargs):165        """Check if requested scopes are within a scope of the refresh token.166 167        When access tokens are refreshed the scope of the new token168        needs to be within the scope of the original token. This is169        ensured by checking that all requested scopes strings are on170        the list returned by the get_original_scopes. If this check171        fails, is_within_original_scope is called. The method can be172        used in situations where returning all valid scopes from the173        get_original_scopes is not practical.174 175        :param request_scopes: A list of scopes that were requested by client.176        :param refresh_token: Unicode refresh_token.177        :param request: OAuthlib request.178        :type request: oauthlib.common.Request179        :rtype: True or False180 181        Method is used by:182            - Refresh token grant183        """184        return False185 186    def introspect_token(self, token, token_type_hint, request, *args, **kwargs):187        """Introspect an access or refresh token.188 189        Called once the introspect request is validated. This method should190        verify the *token* and either return a dictionary with the list of191        claims associated, or `None` in case the token is unknown.192 193        Below the list of registered claims you should be interested in:194 195        - scope : space-separated list of scopes196        - client_id : client identifier197        - username : human-readable identifier for the resource owner198        - token_type : type of the token199        - exp : integer timestamp indicating when this token will expire200        - iat : integer timestamp indicating when this token was issued201        - nbf : integer timestamp indicating when it can be "not-before" used202        - sub : subject of the token - identifier of the resource owner203        - aud : list of string identifiers representing the intended audience204        - iss : string representing issuer of this token205        - jti : string identifier for the token206 207        Note that most of them are coming directly from JWT RFC. More details208        can be found in `Introspect Claims`_ or `JWT Claims`_.209 210        The implementation can use *token_type_hint* to improve lookup211        efficiency, but must fallback to other types to be compliant with RFC.212 213        The dict of claims is added to request.token after this method.214 215        :param token: The token string.216        :param token_type_hint: access_token or refresh_token.217        :param request: OAuthlib request.218        :type request: oauthlib.common.Request219 220        Method is used by:221            - Introspect Endpoint (all grants are compatible)222 223        .. _`Introspect Claims`: https://tools.ietf.org/html/rfc7662#section-2.2224        .. _`JWT Claims`: https://tools.ietf.org/html/rfc7519#section-4225        """226        raise NotImplementedError('Subclasses must implement this method.')227 228    def invalidate_authorization_code(self, client_id, code, request, *args, **kwargs):229        """Invalidate an authorization code after use.230 231        :param client_id: Unicode client identifier.232        :param code: The authorization code grant (request.code).233        :param request: OAuthlib request.234        :type request: oauthlib.common.Request235 236        Method is used by:237            - Authorization Code Grant238        """239        raise NotImplementedError('Subclasses must implement this method.')240 241    def revoke_token(self, token, token_type_hint, request, *args, **kwargs):242        """Revoke an access or refresh token.243 244        :param token: The token string.245        :param token_type_hint: access_token or refresh_token.246        :param request: OAuthlib request.247        :type request: oauthlib.common.Request248 249        Method is used by:250            - Revocation Endpoint251        """252        raise NotImplementedError('Subclasses must implement this method.')253 254    def rotate_refresh_token(self, request):255        """Determine whether to rotate the refresh token. Default, yes.256 257        When access tokens are refreshed the old refresh token can be kept258        or replaced with a new one (rotated). Return True to rotate and259        and False for keeping original.260 261        :param request: OAuthlib request.262        :type request: oauthlib.common.Request263        :rtype: True or False264 265        Method is used by:266            - Refresh Token Grant267        """268        return True269 270    def save_authorization_code(self, client_id, code, request, *args, **kwargs):271        """Persist the authorization_code.272 273        The code should at minimum be stored with:274            - the client_id (``client_id``)275            - the redirect URI used (``request.redirect_uri``)276            - a resource owner / user (``request.user``)277            - the authorized scopes (``request.scopes``)278 279        To support PKCE, you MUST associate the code with:280            - Code Challenge (``request.code_challenge``) and281            - Code Challenge Method (``request.code_challenge_method``)282 283        To support OIDC, you MUST associate the code with:284            - nonce, if present (``code["nonce"]``)285 286        The ``code`` argument is actually a dictionary, containing at least a287        ``code`` key with the actual authorization code:288 289            ``{'code': 'sdf345jsdf0934f'}``290 291        It may also have a ``claims`` parameter which, when present, will be a dict292        deserialized from JSON as described at293        http://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter294        This value should be saved in this method and used again in ``.validate_code``.295 296        :param client_id: Unicode client identifier.297        :param code: A dict of the authorization code grant and, optionally, state.298        :param request: OAuthlib request.299        :type request: oauthlib.common.Request300 301        Method is used by:302            - Authorization Code Grant303        """304        raise NotImplementedError('Subclasses must implement this method.')305 306    def save_token(self, token, request, *args, **kwargs):307        """Persist the token with a token type specific method.308 309        Currently, only save_bearer_token is supported.310 311        :param token: A (Bearer) token dict.312        :param request: OAuthlib request.313        :type request: oauthlib.common.Request314        """315        return self.save_bearer_token(token, request, *args, **kwargs)316 317    def save_bearer_token(self, token, request, *args, **kwargs):318        """Persist the Bearer token.319 320        The Bearer token should at minimum be associated with:321            - a client and it's client_id, if available322            - a resource owner / user (request.user)323            - authorized scopes (request.scopes)324            - an expiration time325            - a refresh token, if issued326            - a claims document, if present in request.claims327 328        The Bearer token dict may hold a number of items::329 330            {331                'token_type': 'Bearer',332                'access_token': 'askfjh234as9sd8',333                'expires_in': 3600,334                'scope': 'string of space separated authorized scopes',335                'refresh_token': '23sdf876234',  # if issued336                'state': 'given_by_client',  # if supplied by client (implicit ONLY)337            }338 339        Note that while "scope" is a string-separated list of authorized scopes,340        the original list is still available in request.scopes.341 342        The token dict is passed as a reference so any changes made to the dictionary343        will go back to the user.  If additional information must return to the client344        user, and it is only possible to get this information after writing the token345        to storage, it should be added to the token dictionary.  If the token346        dictionary must be modified but the changes should not go back to the user,347        a copy of the dictionary must be made before making the changes.348 349        Also note that if an Authorization Code grant request included a valid claims350        parameter (for OpenID Connect) then the request.claims property will contain351        the claims dict, which should be saved for later use when generating the352        id_token and/or UserInfo response content.353 354        :param token: A Bearer token dict.355        :param request: OAuthlib request.356        :type request: oauthlib.common.Request357        :rtype: The default redirect URI for the client358 359        Method is used by all core grant types issuing Bearer tokens:360            - Authorization Code Grant361            - Implicit Grant362            - Resource Owner Password Credentials Grant (might not associate a client)363            - Client Credentials grant364        """365        raise NotImplementedError('Subclasses must implement this method.')366 367    def validate_bearer_token(self, token, scopes, request):368        """Ensure the Bearer token is valid and authorized access to scopes.369 370        :param token: A string of random characters.371        :param scopes: A list of scopes associated with the protected resource.372        :param request: OAuthlib request.373        :type request: oauthlib.common.Request374 375        A key to OAuth 2 security and restricting impact of leaked tokens is376        the short expiration time of tokens, *always ensure the token has not377        expired!*.378 379        Two different approaches to scope validation:380 381            1) all(scopes). The token must be authorized access to all scopes382                            associated with the resource. For example, the383                            token has access to ``read-only`` and ``images``,384                            thus the client can view images but not upload new.385                            Allows for fine grained access control through386                            combining various scopes.387 388            2) any(scopes). The token must be authorized access to one of the389                            scopes associated with the resource. For example,390                            token has access to ``read-only-images``.391                            Allows for fine grained, although arguably less392                            convenient, access control.393 394        A powerful way to use scopes would mimic UNIX ACLs and see a scope395        as a group with certain privileges. For a restful API these might396        map to HTTP verbs instead of read, write and execute.397 398        Note, the request.user attribute can be set to the resource owner399        associated with this token. Similarly the request.client and400        request.scopes attribute can be set to associated client object401        and authorized scopes. If you then use a decorator such as the402        one provided for django these attributes will be made available403        in all protected views as keyword arguments.404 405        :param token: Unicode Bearer token406        :param scopes: List of scopes (defined by you)407        :param request: OAuthlib request.408        :type request: oauthlib.common.Request409        :rtype: True or False410 411        Method is indirectly used by all core Bearer token issuing grant types:412            - Authorization Code Grant413            - Implicit Grant414            - Resource Owner Password Credentials Grant415            - Client Credentials Grant416        """417        raise NotImplementedError('Subclasses must implement this method.')418 419    def validate_client_id(self, client_id, request, *args, **kwargs):420        """Ensure client_id belong to a valid and active client.421 422        Note, while not strictly necessary it can often be very convenient423        to set request.client to the client object associated with the424        given client_id.425 426        :param client_id: Unicode client identifier.427        :param request: OAuthlib request.428        :type request: oauthlib.common.Request429        :rtype: True or False430 431        Method is used by:432            - Authorization Code Grant433            - Implicit Grant434        """435        raise NotImplementedError('Subclasses must implement this method.')436 437    def validate_code(self, client_id, code, client, request, *args, **kwargs):438        """Verify that the authorization_code is valid and assigned to the given439        client.440 441        Before returning true, set the following based on the information stored442        with the code in 'save_authorization_code':443 444            - request.user445            - request.scopes446            - request.claims (if given)447 448        OBS! The request.user attribute should be set to the resource owner449        associated with this authorization code. Similarly request.scopes450        must also be set.451 452        The request.claims property, if it was given, should assigned a dict.453 454        If PKCE is enabled (see 'is_pkce_required' and 'save_authorization_code')455        you MUST set the following based on the information stored:456 457            - request.code_challenge458            - request.code_challenge_method459 460        :param client_id: Unicode client identifier.461        :param code: Unicode authorization code.462        :param client: Client object set by you, see ``.authenticate_client``.463        :param request: OAuthlib request.464        :type request: oauthlib.common.Request465        :rtype: True or False466 467        Method is used by:468            - Authorization Code Grant469        """470        raise NotImplementedError('Subclasses must implement this method.')471 472    def validate_grant_type(self, client_id, grant_type, client, request, *args, **kwargs):473        """Ensure client is authorized to use the grant_type requested.474 475        :param client_id: Unicode client identifier.476        :param grant_type: Unicode grant type, i.e. authorization_code, password.477        :param client: Client object set by you, see ``.authenticate_client``.478        :param request: OAuthlib request.479        :type request: oauthlib.common.Request480        :rtype: True or False481 482        Method is used by:483            - Authorization Code Grant484            - Resource Owner Password Credentials Grant485            - Client Credentials Grant486            - Refresh Token Grant487        """488        raise NotImplementedError('Subclasses must implement this method.')489 490    def validate_redirect_uri(self, client_id, redirect_uri, request, *args, **kwargs):491        """Ensure client is authorized to redirect to the redirect_uri requested.492 493        All clients should register the absolute URIs of all URIs they intend494        to redirect to. The registration is outside of the scope of oauthlib.495 496        :param client_id: Unicode client identifier.497        :param redirect_uri: Unicode absolute URI.498        :param request: OAuthlib request.499        :type request: oauthlib.common.Request500        :rtype: True or False501 502        Method is used by:503            - Authorization Code Grant504            - Implicit Grant505        """506        raise NotImplementedError('Subclasses must implement this method.')507 508    def validate_refresh_token(self, refresh_token, client, request, *args, **kwargs):509        """Ensure the Bearer token is valid and authorized access to scopes.510 511        OBS! The request.user attribute should be set to the resource owner512        associated with this refresh token.513 514        :param refresh_token: Unicode refresh token.515        :param client: Client object set by you, see ``.authenticate_client``.516        :param request: OAuthlib request.517        :type request: oauthlib.common.Request518        :rtype: True or False519 520        Method is used by:521            - Authorization Code Grant (indirectly by issuing refresh tokens)522            - Resource Owner Password Credentials Grant (also indirectly)523            - Refresh Token Grant524        """525        raise NotImplementedError('Subclasses must implement this method.')526 527    def validate_response_type(self, client_id, response_type, client, request, *args, **kwargs):528        """Ensure client is authorized to use the response_type requested.529 530        :param client_id: Unicode client identifier.531        :param response_type: Unicode response type, i.e. code, token.532        :param client: Client object set by you, see ``.authenticate_client``.533        :param request: OAuthlib request.534        :type request: oauthlib.common.Request535        :rtype: True or False536 537        Method is used by:538            - Authorization Code Grant539            - Implicit Grant540        """541        raise NotImplementedError('Subclasses must implement this method.')542 543    def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs):544        """Ensure the client is authorized access to requested scopes.545 546        :param client_id: Unicode client identifier.547        :param scopes: List of scopes (defined by you).548        :param client: Client object set by you, see ``.authenticate_client``.549        :param request: OAuthlib request.550        :type request: oauthlib.common.Request551        :rtype: True or False552 553        Method is used by all core grant types:554            - Authorization Code Grant555            - Implicit Grant556            - Resource Owner Password Credentials Grant557            - Client Credentials Grant558        """559        raise NotImplementedError('Subclasses must implement this method.')560 561    def validate_user(self, username, password, client, request, *args, **kwargs):562        """Ensure the username and password is valid.563 564        OBS! The validation should also set the user attribute of the request565        to a valid resource owner, i.e. request.user = username or similar. If566        not set you will be unable to associate a token with a user in the567        persistence method used (commonly, save_bearer_token).568 569        :param username: Unicode username.570        :param password: Unicode password.571        :param client: Client object set by you, see ``.authenticate_client``.572        :param request: OAuthlib request.573        :type request: oauthlib.common.Request574        :rtype: True or False575 576        Method is used by:577            - Resource Owner Password Credentials Grant578        """579        raise NotImplementedError('Subclasses must implement this method.')580 581    def is_pkce_required(self, client_id, request):582        """Determine if current request requires PKCE. Default, False.583        This is called for both "authorization" and "token" requests.584 585        Override this method by ``return True`` to enable PKCE for everyone.586        You might want to enable it only for public clients.587        Note that PKCE can also be used in addition of a client authentication.588 589        OAuth 2.0 public clients utilizing the Authorization Code Grant are590        susceptible to the authorization code interception attack.  This591        specification describes the attack as well as a technique to mitigate592        against the threat through the use of Proof Key for Code Exchange593        (PKCE, pronounced "pixy"). See `RFC7636`_.594 595        :param client_id: Client identifier.596        :param request: OAuthlib request.597        :type request: oauthlib.common.Request598        :rtype: True or False599 600        Method is used by:601            - Authorization Code Grant602 603        .. _`RFC7636`: https://tools.ietf.org/html/rfc7636604        """605        return False606 607    def get_code_challenge(self, code, request):608        """Is called for every "token" requests.609 610        When the server issues the authorization code in the authorization611        response, it MUST associate the ``code_challenge`` and612        ``code_challenge_method`` values with the authorization code so it can613        be verified later.614 615        Typically, the ``code_challenge`` and ``code_challenge_method`` values616        are stored in encrypted form in the ``code`` itself but could617        alternatively be stored on the server associated with the code.  The618        server MUST NOT include the ``code_challenge`` value in client requests619        in a form that other entities can extract.620 621        Return the ``code_challenge`` associated to the code.622        If ``None`` is returned, code is considered to not be associated to any623        challenges.624 625        :param code: Authorization code.626        :param request: OAuthlib request.627        :type request: oauthlib.common.Request628        :rtype: code_challenge string629 630        Method is used by:631            - Authorization Code Grant - when PKCE is active632 633        """634        return None635 636    def get_code_challenge_method(self, code, request):637        """Is called during the "token" request processing, when a638        ``code_verifier`` and a ``code_challenge`` has been provided.639 640        See ``.get_code_challenge``.641 642        Must return ``plain`` or ``S256``. You can return a custom value if you have643        implemented your own ``AuthorizationCodeGrant`` class.644 645        :param code: Authorization code.646        :param request: OAuthlib request.647        :type request: oauthlib.common.Request648        :rtype: code_challenge_method string649 650        Method is used by:651            - Authorization Code Grant - when PKCE is active652 653        """654        raise NotImplementedError('Subclasses must implement this method.')655 656    def is_origin_allowed(self, client_id, origin, request, *args, **kwargs):657        """Indicate if the given origin is allowed to access the token endpoint658        via Cross-Origin Resource Sharing (CORS).  CORS is used by browser-based659        clients, such as Single-Page Applications, to perform the Authorization660        Code Grant.661 662        (Note:  If performing Authorization Code Grant via a public client such663        as a browser, you should use PKCE as well.)664 665        If this method returns true, the appropriate CORS headers will be added666        to the response.  By default this method always returns False, meaning667        CORS is disabled.668 669        :param client_id: Unicode client identifier.670        :param redirect_uri: Unicode origin.671        :param request: OAuthlib request.672        :type request: oauthlib.common.Request673        :rtype: bool674 675        Method is used by:676            - Authorization Code Grant677            - Refresh Token Grant678 679        """680        return False681 
codekingpro/portable-devtools · Team Ai