1# -*- coding: utf-8 -*- 
    2""" 
    3oauthlib.oauth1.rfc5849.endpoints.authorization 
    4~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    5 
    6This module is an implementation of various logic needed 
    7for signing and checking OAuth 1.0 RFC 5849 requests. 
    8""" 
    9from urllib.parse import urlencode 
    10 
    11from oauthlib.common import add_params_to_uri 
    12 
    13from .. import errors 
    14from .base import BaseEndpoint 
    15 
    16 
    17class AuthorizationEndpoint(BaseEndpoint): 
    18 
    19    """An endpoint responsible for letting authenticated users authorize access 
    20    to their protected resources to a client. 
    21 
    22    Typical use would be to have two views, one for displaying the authorization 
    23    form and one to process said form on submission. 
    24 
    25    The first view will want to utilize ``get_realms_and_credentials`` to fetch 
    26    requested realms and useful client credentials, such as name and 
    27    description, to be used when creating the authorization form. 
    28 
    29    During form processing you can use ``create_authorization_response`` to 
    30    validate the request, create a verifier as well as prepare the final 
    31    redirection URI used to send the user back to the client. 
    32 
    33    See :doc:`/oauth1/validator` for details on which validator methods to implement 
    34    for this endpoint. 
    35    """ 
    36 
    37    def create_verifier(self, request, credentials): 
    38        """Create and save a new request token. 
    39 
    40        :param request: OAuthlib request. 
    41        :type request: oauthlib.common.Request 
    42        :param credentials: A dict of extra token credentials. 
    43        :returns: The verifier as a dict. 
    44        """ 
    45        verifier = { 
    46            'oauth_token': request.resource_owner_key, 
    47            'oauth_verifier': self.token_generator(), 
    48        } 
    49        verifier.update(credentials) 
    50        self.request_validator.save_verifier( 
    51            request.resource_owner_key, verifier, request) 
    52        return verifier 
    53 
    54    def create_authorization_response(self, uri, http_method='GET', body=None, 
    55                                      headers=None, realms=None, credentials=None): 
    56        """Create an authorization response, with a new request token if valid. 
    57 
    58        :param uri: The full URI of the token request. 
    59        :param http_method: A valid HTTP verb, i.e. GET, POST, PUT, HEAD, etc. 
    60        :param body: The request body as a string. 
    61        :param headers: The request headers as a dict. 
    62        :param credentials: A list of credentials to include in the verifier. 
    63        :returns: A tuple of 3 elements. 
    64                  1. A dict of headers to set on the response. 
    65                  2. The response body as a string. 
    66                  3. The response status code as an integer. 
    67 
    68        If the callback URI tied to the current token is "oob", a response with 
    69        a 200 status code will be returned. In this case, it may be desirable to 
    70        modify the response to better display the verifier to the client. 
    71 
    72        An example of an authorization request:: 
    73 
    74            >>> from your_validator import your_validator 
    75            >>> from oauthlib.oauth1 import AuthorizationEndpoint 
    76            >>> endpoint = AuthorizationEndpoint(your_validator) 
    77            >>> h, b, s = endpoint.create_authorization_response( 
    78            ...     'https://your.provider/authorize?oauth_token=...', 
    79            ...     credentials={ 
    80            ...         'extra': 'argument', 
    81            ...     }) 
    82            >>> h 
    83            {'Location': 'https://the.client/callback?oauth_verifier=...&extra=argument'} 
    84            >>> b 
    85            None 
    86            >>> s 
    87            302 
    88 
    89        An example of a request with an "oob" callback:: 
    90 
    91            >>> from your_validator import your_validator 
    92            >>> from oauthlib.oauth1 import AuthorizationEndpoint 
    93            >>> endpoint = AuthorizationEndpoint(your_validator) 
    94            >>> h, b, s = endpoint.create_authorization_response( 
    95            ...     'https://your.provider/authorize?foo=bar', 
    96            ...     credentials={ 
    97            ...         'extra': 'argument', 
    98            ...     }) 
    99            >>> h 
    100            {'Content-Type': 'application/x-www-form-urlencoded'} 
    101            >>> b 
    102            'oauth_verifier=...&extra=argument' 
    103            >>> s 
    104            200 
    105        """ 
    106        request = self._create_request(uri, http_method=http_method, body=body, 
    107                                       headers=headers) 
    108 
    109        if not request.resource_owner_key: 
    110            raise errors.InvalidRequestError( 
    111                'Missing mandatory parameter oauth_token.') 
    112        if not self.request_validator.verify_request_token( 
    113                request.resource_owner_key, request): 
    114            raise errors.InvalidClientError() 
    115 
    116        request.realms = realms 
    117        if (request.realms and not self.request_validator.verify_realms( 
    118                request.resource_owner_key, request.realms, request)): 
    119            raise errors.InvalidRequestError( 
    120                description=('User granted access to realms outside of ' 
    121                             'what the client may request.')) 
    122 
    123        verifier = self.create_verifier(request, credentials or {}) 
    124        redirect_uri = self.request_validator.get_redirect_uri( 
    125            request.resource_owner_key, request) 
    126        if redirect_uri == 'oob': 
    127            response_headers = { 
    128                'Content-Type': 'application/x-www-form-urlencoded'} 
    129            response_body = urlencode(verifier) 
    130            return response_headers, response_body, 200 
    131        else: 
    132            populated_redirect = add_params_to_uri( 
    133                redirect_uri, verifier.items()) 
    134            return {'Location': populated_redirect}, None, 302 
    135 
    136    def get_realms_and_credentials(self, uri, http_method='GET', body=None, 
    137                                   headers=None): 
    138        """Fetch realms and credentials for the presented request token. 
    139 
    140        :param uri: The full URI of the token request. 
    141        :param http_method: A valid HTTP verb, i.e. GET, POST, PUT, HEAD, etc. 
    142        :param body: The request body as a string. 
    143        :param headers: The request headers as a dict. 
    144        :returns: A tuple of 2 elements. 
    145                  1. A list of request realms. 
    146                  2. A dict of credentials which may be useful in creating the 
    147                  authorization form. 
    148        """ 
    149        request = self._create_request(uri, http_method=http_method, body=body, 
    150                                       headers=headers) 
    151 
    152        if not self.request_validator.verify_request_token( 
    153                request.resource_owner_key, request): 
    154            raise errors.InvalidClientError() 
    155 
    156        realms = self.request_validator.get_realms( 
    157            request.resource_owner_key, request) 
    158        return realms, {'resource_owner_key': request.resource_owner_key}