1""" 
    2oauthlib.oauth2.rfc6749.endpoint.introspect 
    3~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    4 
    5An implementation of the OAuth 2.0 `Token Introspection`. 
    6 
    7.. _`Token Introspection`: https://tools.ietf.org/html/rfc7662 
    8""" 
    9import json 
    10import logging 
    11 
    12from oauthlib.common import Request 
    13 
    14from ..errors import OAuth2Error 
    15from .base import BaseEndpoint, catch_errors_and_unavailability 
    16 
    17log = logging.getLogger(__name__) 
    18 
    19 
    20class IntrospectEndpoint(BaseEndpoint): 
    21 
    22    """Introspect token endpoint. 
    23 
    24   This endpoint defines a method to query an OAuth 2.0 authorization 
    25   server to determine the active state of an OAuth 2.0 token and to 
    26   determine meta-information about this token. OAuth 2.0 deployments 
    27   can use this method to convey information about the authorization 
    28   context of the token from the authorization server to the protected 
    29   resource. 
    30 
    31   To prevent the values of access tokens from leaking into 
    32   server-side logs via query parameters, an authorization server 
    33   offering token introspection MAY disallow the use of HTTP GET on 
    34   the introspection endpoint and instead require the HTTP POST method 
    35   to be used at the introspection endpoint. 
    36   """ 
    37 
    38    valid_token_types = ('access_token', 'refresh_token') 
    39    valid_request_methods = ('POST',) 
    40 
    41    def __init__(self, request_validator, supported_token_types=None): 
    42        BaseEndpoint.__init__(self) 
    43        self.request_validator = request_validator 
    44        self.supported_token_types = ( 
    45            supported_token_types or self.valid_token_types) 
    46 
    47    @catch_errors_and_unavailability 
    48    def create_introspect_response(self, uri, http_method='POST', body=None, 
    49                                   headers=None): 
    50        """Create introspect valid or invalid response 
    51 
    52        If the authorization server is unable to determine the state 
    53        of the token without additional information, it SHOULD return 
    54        an introspection response indicating the token is not active 
    55        as described in Section 2.2. 
    56        """ 
    57        resp_headers = { 
    58            'Content-Type': 'application/json', 
    59            'Cache-Control': 'no-store', 
    60            'Pragma': 'no-cache', 
    61        } 
    62        request = Request(uri, http_method, body, headers) 
    63        try: 
    64            self.validate_introspect_request(request) 
    65            log.debug('Token introspect valid for %r.', request) 
    66        except OAuth2Error as e: 
    67            log.debug('Client error during validation of %r. %r.', request, e) 
    68            resp_headers.update(e.headers) 
    69            return resp_headers, e.json, e.status_code 
    70 
    71        claims = self.request_validator.introspect_token( 
    72            request.token, 
    73            request.token_type_hint, 
    74            request 
    75        ) 
    76        if claims is None: 
    77            return resp_headers, json.dumps({'active': False}), 200 
    78        if "active" in claims: 
    79            claims.pop("active") 
    80        return resp_headers, json.dumps(dict(active=True, **claims)), 200 
    81 
    82    def validate_introspect_request(self, request): 
    83        """Ensure the request is valid. 
    84 
    85        The protected resource calls the introspection endpoint using 
    86        an HTTP POST request with parameters sent as 
    87        "application/x-www-form-urlencoded". 
    88 
    89        * token REQUIRED.  The string value of the token. 
    90        * token_type_hint OPTIONAL. 
    91 
    92        A hint about the type of the token submitted for 
    93        introspection.  The protected resource MAY pass this parameter to 
    94        help the authorization server optimize the token lookup.  If the 
    95        server is unable to locate the token using the given hint, it MUST 
    96        extend its search across all of its supported token types.  An 
    97        authorization server MAY ignore this parameter, particularly if it 
    98        is able to detect the token type automatically. 
    99 
    100        *  access_token: An Access Token as defined in [`RFC6749`], `section 1.4`_ 
    101        *  refresh_token: A Refresh Token as defined in [`RFC6749`], `section 1.5`_ 
    102 
    103        The introspection endpoint MAY accept other OPTIONAL 
    104        parameters to provide further context to the query.  For 
    105        instance, an authorization server may desire to know the IP 
    106        address of the client accessing the protected resource to 
    107        determine if the correct client is likely to be presenting the 
    108        token.  The definition of this or any other parameters are 
    109        outside the scope of this specification, to be defined by 
    110        service documentation or extensions to this specification. 
    111 
    112        .. _`section 1.4`: http://tools.ietf.org/html/rfc6749#section-1.4 
    113        .. _`section 1.5`: http://tools.ietf.org/html/rfc6749#section-1.5 
    114        .. _`RFC6749`: http://tools.ietf.org/html/rfc6749 
    115        """ 
    116        self._raise_on_bad_method(request) 
    117        self._raise_on_bad_post_request(request) 
    118        self._raise_on_missing_token(request) 
    119        self._raise_on_invalid_client(request) 
    120        self._raise_on_unsupported_token(request)