PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/social_auth/backends/contrib/bitbucket.py

https://bitbucket.org/nguyenivan/topsnam
Python | 109 lines | 88 code | 5 blank | 16 comment | 0 complexity | 679bc953deb6e32b1995712e63d5e096 MD5 | raw file
  1. """
  2. Bitbucket OAuth support.
  3. This adds support for Bitbucket OAuth service. An application must
  4. be registered first on Bitbucket and the settings BITBUCKET_CONSUMER_KEY
  5. and BITBUCKET_CONSUMER_SECRET must be defined with the corresponding
  6. values.
  7. By default username, email, token expiration time, first name and last name are
  8. stored in extra_data field, check OAuthBackend class for details on how to
  9. extend it.
  10. """
  11. from django.utils import simplejson
  12. from social_auth.backends import ConsumerBasedOAuth, OAuthBackend, USERNAME
  13. from urllib import urlopen
  14. from social_auth.utils import setting
  15. # Bitbucket configuration
  16. BITBUCKET_SERVER = 'bitbucket.org/api/1.0'
  17. BITBUCKET_REQUEST_TOKEN_URL = 'https://%s/oauth/request_token' % \
  18. BITBUCKET_SERVER
  19. BITBUCKET_ACCESS_TOKEN_URL = 'https://%s/oauth/access_token' % BITBUCKET_SERVER
  20. BITBUCKET_AUTHORIZATION_URL = 'https://%s/oauth/authenticate' % \
  21. BITBUCKET_SERVER
  22. BITBUCKET_EMAIL_DATA_URL = 'https://%s/emails/' % BITBUCKET_SERVER
  23. BITBUCKET_USER_DATA_URL = 'https://%s/users/' % BITBUCKET_SERVER
  24. class BitbucketBackend(OAuthBackend):
  25. """Bitbucket OAuth authentication backend"""
  26. name = 'bitbucket'
  27. EXTRA_DATA = [
  28. ('username', 'username'),
  29. ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires')),
  30. ('email', 'email'),
  31. ('first_name', 'first_name'),
  32. ('last_name', 'last_name')
  33. ]
  34. def get_user_details(self, response):
  35. """Return user details from Bitbucket account"""
  36. return {USERNAME: response.get('username'),
  37. 'email': response.get('email'),
  38. 'fullname': ' '.join((response.get('first_name'),
  39. response.get('last_name'))),
  40. 'first_name': response.get('first_name'),
  41. 'last_name': response.get('last_name')}
  42. def get_user_id(self, details, response):
  43. """Return the user id, Bitbucket only provides username as a unique
  44. identifier"""
  45. return response['username']
  46. @classmethod
  47. def tokens(cls, instance):
  48. """Return the tokens needed to authenticate the access to any API the
  49. service might provide. Bitbucket uses a pair of OAuthToken consisting
  50. on a oauth_token and oauth_token_secret.
  51. instance must be a UserSocialAuth instance.
  52. """
  53. token = super(BitbucketBackend, cls).tokens(instance)
  54. if token and 'access_token' in token:
  55. token = dict(tok.split('=')
  56. for tok in token['access_token'].split('&'))
  57. return token
  58. class BitbucketAuth(ConsumerBasedOAuth):
  59. """Bitbucket OAuth authentication mechanism"""
  60. AUTHORIZATION_URL = BITBUCKET_AUTHORIZATION_URL
  61. REQUEST_TOKEN_URL = BITBUCKET_REQUEST_TOKEN_URL
  62. ACCESS_TOKEN_URL = BITBUCKET_ACCESS_TOKEN_URL
  63. SERVER_URL = BITBUCKET_SERVER
  64. AUTH_BACKEND = BitbucketBackend
  65. SETTINGS_KEY_NAME = 'BITBUCKET_CONSUMER_KEY'
  66. SETTINGS_SECRET_NAME = 'BITBUCKET_CONSUMER_SECRET'
  67. def user_data(self, access_token):
  68. """Return user data provided"""
  69. # Bitbucket has a bit of an indirect route to obtain user data from an
  70. # authenticated query: First obtain the user's email via an
  71. # authenticated GET
  72. url = BITBUCKET_EMAIL_DATA_URL
  73. request = self.oauth_request(access_token, url)
  74. response = self.fetch_response(request)
  75. try:
  76. # Then retrieve the user's primary email address or the top email
  77. email_addresses = simplejson.loads(response)
  78. for email_address in reversed(email_addresses):
  79. if email_address['active']:
  80. email = email_address['email']
  81. if email_address['primary']:
  82. break
  83. # Then return the user data using a normal GET with the
  84. # BITBUCKET_USER_DATA_URL and the user's email
  85. response = urlopen(BITBUCKET_USER_DATA_URL + email)
  86. user_details = simplejson.load(response)['user']
  87. user_details['email'] = email
  88. return user_details
  89. except ValueError:
  90. return None
  91. return None
  92. # Backend definition
  93. BACKENDS = {
  94. 'bitbucket': BitbucketAuth,
  95. }