authorization.py 6.7 KB

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