oauth1_auth.py 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. import logging
  4. from oauthlib.common import extract_params
  5. from oauthlib.oauth1 import Client, SIGNATURE_HMAC, SIGNATURE_TYPE_AUTH_HEADER
  6. from oauthlib.oauth1 import SIGNATURE_TYPE_BODY
  7. from requests.compat import is_py3
  8. from requests.utils import to_native_string
  9. from requests.auth import AuthBase
  10. CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded'
  11. CONTENT_TYPE_MULTI_PART = 'multipart/form-data'
  12. if is_py3:
  13. unicode = str
  14. log = logging.getLogger(__name__)
  15. # OBS!: Correct signing of requests are conditional on invoking OAuth1
  16. # as the last step of preparing a request, or at least having the
  17. # content-type set properly.
  18. class OAuth1(AuthBase):
  19. """Signs the request using OAuth 1 (RFC5849)"""
  20. client_class = Client
  21. def __init__(self, client_key,
  22. client_secret=None,
  23. resource_owner_key=None,
  24. resource_owner_secret=None,
  25. callback_uri=None,
  26. signature_method=SIGNATURE_HMAC,
  27. signature_type=SIGNATURE_TYPE_AUTH_HEADER,
  28. rsa_key=None, verifier=None,
  29. decoding='utf-8',
  30. client_class=None,
  31. force_include_body=False,
  32. **kwargs):
  33. try:
  34. signature_type = signature_type.upper()
  35. except AttributeError:
  36. pass
  37. client_class = client_class or self.client_class
  38. self.force_include_body = force_include_body
  39. self.client = client_class(client_key, client_secret, resource_owner_key,
  40. resource_owner_secret, callback_uri, signature_method,
  41. signature_type, rsa_key, verifier, decoding=decoding, **kwargs)
  42. def __call__(self, r):
  43. """Add OAuth parameters to the request.
  44. Parameters may be included from the body if the content-type is
  45. urlencoded, if no content type is set a guess is made.
  46. """
  47. # Overwriting url is safe here as request will not modify it past
  48. # this point.
  49. log.debug('Signing request %s using client %s', r, self.client)
  50. content_type = r.headers.get('Content-Type', '')
  51. if (not content_type and extract_params(r.body)
  52. or self.client.signature_type == SIGNATURE_TYPE_BODY):
  53. content_type = CONTENT_TYPE_FORM_URLENCODED
  54. if not isinstance(content_type, unicode):
  55. content_type = content_type.decode('utf-8')
  56. is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in content_type)
  57. log.debug('Including body in call to sign: %s',
  58. is_form_encoded or self.force_include_body)
  59. if is_form_encoded:
  60. r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
  61. r.url, headers, r.body = self.client.sign(
  62. unicode(r.url), unicode(r.method), r.body or '', r.headers)
  63. elif self.force_include_body:
  64. # To allow custom clients to work on non form encoded bodies.
  65. r.url, headers, r.body = self.client.sign(
  66. unicode(r.url), unicode(r.method), r.body or '', r.headers)
  67. else:
  68. # Omit body data in the signing of non form-encoded requests
  69. r.url, headers, _ = self.client.sign(
  70. unicode(r.url), unicode(r.method), None, r.headers)
  71. r.prepare_headers(headers)
  72. r.url = to_native_string(r.url)
  73. log.debug('Updated url: %s', r.url)
  74. log.debug('Updated headers: %s', headers)
  75. log.debug('Updated body: %r', r.body)
  76. return r