token.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. """
  2. oauthlib.oauth2.rfc6749
  3. ~~~~~~~~~~~~~~~~~~~~~~~
  4. This module is an implementation of various logic needed
  5. for consuming and providing OAuth 2.0 RFC6749.
  6. """
  7. import logging
  8. from oauthlib.common import Request
  9. from oauthlib.oauth2.rfc6749 import utils
  10. from .base import BaseEndpoint, catch_errors_and_unavailability
  11. log = logging.getLogger(__name__)
  12. class TokenEndpoint(BaseEndpoint):
  13. """Token issuing endpoint.
  14. The token endpoint is used by the client to obtain an access token by
  15. presenting its authorization grant or refresh token. The token
  16. endpoint is used with every authorization grant except for the
  17. implicit grant type (since an access token is issued directly).
  18. The means through which the client obtains the location of the token
  19. endpoint are beyond the scope of this specification, but the location
  20. is typically provided in the service documentation.
  21. The endpoint URI MAY include an "application/x-www-form-urlencoded"
  22. formatted (per `Appendix B`_) query component,
  23. which MUST be retained when adding additional query parameters. The
  24. endpoint URI MUST NOT include a fragment component::
  25. https://example.com/path?query=component # OK
  26. https://example.com/path?query=component#fragment # Not OK
  27. Since requests to the token endpoint result in the transmission of
  28. clear-text credentials (in the HTTP request and response), the
  29. authorization server MUST require the use of TLS as described in
  30. Section 1.6 when sending requests to the token endpoint::
  31. # We will deny any request which URI schema is not with https
  32. The client MUST use the HTTP "POST" method when making access token
  33. requests::
  34. # HTTP method is currently not enforced
  35. Parameters sent without a value MUST be treated as if they were
  36. omitted from the request. The authorization server MUST ignore
  37. unrecognized request parameters. Request and response parameters
  38. MUST NOT be included more than once::
  39. # Delegated to each grant type.
  40. .. _`Appendix B`: https://tools.ietf.org/html/rfc6749#appendix-B
  41. """
  42. valid_request_methods = ('POST',)
  43. def __init__(self, default_grant_type, default_token_type, grant_types):
  44. BaseEndpoint.__init__(self)
  45. self._grant_types = grant_types
  46. self._default_token_type = default_token_type
  47. self._default_grant_type = default_grant_type
  48. @property
  49. def grant_types(self):
  50. return self._grant_types
  51. @property
  52. def default_grant_type(self):
  53. return self._default_grant_type
  54. @property
  55. def default_grant_type_handler(self):
  56. return self.grant_types.get(self.default_grant_type)
  57. @property
  58. def default_token_type(self):
  59. return self._default_token_type
  60. @catch_errors_and_unavailability
  61. def create_token_response(self, uri, http_method='POST', body=None,
  62. headers=None, credentials=None, grant_type_for_scope=None,
  63. claims=None):
  64. """Extract grant_type and route to the designated handler."""
  65. request = Request(
  66. uri, http_method=http_method, body=body, headers=headers)
  67. self.validate_token_request(request)
  68. # 'scope' is an allowed Token Request param in both the "Resource Owner Password Credentials Grant"
  69. # and "Client Credentials Grant" flows
  70. # https://tools.ietf.org/html/rfc6749#section-4.3.2
  71. # https://tools.ietf.org/html/rfc6749#section-4.4.2
  72. request.scopes = utils.scope_to_list(request.scope)
  73. request.extra_credentials = credentials
  74. if grant_type_for_scope:
  75. request.grant_type = grant_type_for_scope
  76. # OpenID Connect claims, if provided. The server using oauthlib might choose
  77. # to implement the claims parameter of the Authorization Request. In this case
  78. # it should retrieve those claims and pass them via the claims argument here,
  79. # as a dict.
  80. if claims:
  81. request.claims = claims
  82. grant_type_handler = self.grant_types.get(request.grant_type,
  83. self.default_grant_type_handler)
  84. log.debug('Dispatching grant_type %s request to %r.',
  85. request.grant_type, grant_type_handler)
  86. return grant_type_handler.create_token_response(
  87. request, self.default_token_type)
  88. def validate_token_request(self, request):
  89. self._raise_on_bad_method(request)
  90. self._raise_on_bad_post_request(request)