/social_auth/backends/contrib/bitbucket.py
Python | 108 lines | 87 code | 5 blank | 16 comment | 0 complexity | 39313c2157998b0a93e0af011c49f751 MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause
- """
- Bitbucket OAuth support.
- This adds support for Bitbucket OAuth service. An application must
- be registered first on Bitbucket and the settings BITBUCKET_CONSUMER_KEY
- and BITBUCKET_CONSUMER_SECRET must be defined with the corresponding
- values.
- By default username, email, token expiration time, first name and last name are
- stored in extra_data field, check OAuthBackend class for details on how to
- extend it.
- """
- from django.utils import simplejson
- from social_auth.backends import ConsumerBasedOAuth, OAuthBackend, USERNAME
- from social_auth.utils import setting, dsa_urlopen
- # Bitbucket configuration
- BITBUCKET_SERVER = 'bitbucket.org/api/1.0'
- BITBUCKET_REQUEST_TOKEN_URL = 'https://%s/oauth/request_token' % \
- BITBUCKET_SERVER
- BITBUCKET_ACCESS_TOKEN_URL = 'https://%s/oauth/access_token' % BITBUCKET_SERVER
- BITBUCKET_AUTHORIZATION_URL = 'https://%s/oauth/authenticate' % \
- BITBUCKET_SERVER
- BITBUCKET_EMAIL_DATA_URL = 'https://%s/emails/' % BITBUCKET_SERVER
- BITBUCKET_USER_DATA_URL = 'https://%s/users/' % BITBUCKET_SERVER
- class BitbucketBackend(OAuthBackend):
- """Bitbucket OAuth authentication backend"""
- name = 'bitbucket'
- EXTRA_DATA = [
- ('username', 'username'),
- ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires')),
- ('email', 'email'),
- ('first_name', 'first_name'),
- ('last_name', 'last_name')
- ]
- def get_user_details(self, response):
- """Return user details from Bitbucket account"""
- return {USERNAME: response.get('username'),
- 'email': response.get('email'),
- 'fullname': ' '.join((response.get('first_name'),
- response.get('last_name'))),
- 'first_name': response.get('first_name'),
- 'last_name': response.get('last_name')}
- def get_user_id(self, details, response):
- """Return the user id, Bitbucket only provides username as a unique
- identifier"""
- return response['username']
- @classmethod
- def tokens(cls, instance):
- """Return the tokens needed to authenticate the access to any API the
- service might provide. Bitbucket uses a pair of OAuthToken consisting
- on a oauth_token and oauth_token_secret.
- instance must be a UserSocialAuth instance.
- """
- token = super(BitbucketBackend, cls).tokens(instance)
- if token and 'access_token' in token:
- token = dict(tok.split('=')
- for tok in token['access_token'].split('&'))
- return token
- class BitbucketAuth(ConsumerBasedOAuth):
- """Bitbucket OAuth authentication mechanism"""
- AUTHORIZATION_URL = BITBUCKET_AUTHORIZATION_URL
- REQUEST_TOKEN_URL = BITBUCKET_REQUEST_TOKEN_URL
- ACCESS_TOKEN_URL = BITBUCKET_ACCESS_TOKEN_URL
- SERVER_URL = BITBUCKET_SERVER
- AUTH_BACKEND = BitbucketBackend
- SETTINGS_KEY_NAME = 'BITBUCKET_CONSUMER_KEY'
- SETTINGS_SECRET_NAME = 'BITBUCKET_CONSUMER_SECRET'
- def user_data(self, access_token):
- """Return user data provided"""
- # Bitbucket has a bit of an indirect route to obtain user data from an
- # authenticated query: First obtain the user's email via an
- # authenticated GET
- url = BITBUCKET_EMAIL_DATA_URL
- request = self.oauth_request(access_token, url)
- response = self.fetch_response(request)
- try:
- # Then retrieve the user's primary email address or the top email
- email_addresses = simplejson.loads(response)
- for email_address in reversed(email_addresses):
- if email_address['active']:
- email = email_address['email']
- if email_address['primary']:
- break
- # Then return the user data using a normal GET with the
- # BITBUCKET_USER_DATA_URL and the user's email
- response = dsa_urlopen(BITBUCKET_USER_DATA_URL + email)
- user_details = simplejson.load(response)['user']
- user_details['email'] = email
- return user_details
- except ValueError:
- return None
- return None
- # Backend definition
- BACKENDS = {
- 'bitbucket': BitbucketAuth,
- }