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)