From: Thomas Whitton Date: Mon, 16 Apr 2012 19:38:35 +0000 (+0100) Subject: Added Bitbucket backend X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=06fff8a6a56a8357174f921410528614e578789e;p=django-social-auth.git Added Bitbucket backend --- diff --git a/README.rst b/README.rst index 93afa6b..7cf60fe 100644 --- a/README.rst +++ b/README.rst @@ -119,6 +119,7 @@ Configuration 'social_auth.backends.contrib.flickr.FlickrBackend', 'social_auth.backends.contrib.instagram.InstagramBackend', 'social_auth.backends.OpenIDBackend', + 'social_auth.backends.contrib.bitbucket.BitbucketBackend', 'django.contrib.auth.backends.ModelBackend', ) @@ -152,6 +153,8 @@ Configuration FLICKR_API_SECRET = '' INSTAGRAM_CLIENT_ID = '' INSTAGRAM_CLIENT_SECRET = '' + BITBUCKET_CONSUMER_KEY = '' + BITBUCKET_CONSUMER_SECRET = '' - Setup login URLs:: @@ -821,6 +824,17 @@ GitHub works similar to Facebook (OAuth). - Also it's possible to define extra permissions with:: GITHUB_EXTENDED_PERMISSIONS = [...] + +Bitbucket +^^^^^^^^^ +Bitbucket works similar to Twitter (OAuth). + +- Register a new application by emailing support@bitbucket.org with an application name and a bit of a description, + +- Fill ``Consumer Key`` and ``Consumer Secret`` values in the settings:: + + BITBUCKET_CONSUMER_KEY = '' + BITBUCKET_CONSUMER_SECRET = '' Dropbox ^^^^^^^ diff --git a/social_auth/backends/contrib/bitbucket.py b/social_auth/backends/contrib/bitbucket.py new file mode 100644 index 0000000..69d4342 --- /dev/null +++ b/social_auth/backends/contrib/bitbucket.py @@ -0,0 +1,99 @@ +""" +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 urllib import urlopen +from social_auth.utils import setting + +# 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: + email = simplejson.loads(response)[0]['email'] + # Then return the user data using a normal GET with the BITBUCKET_USER_DATA_URL and the user's email + response = 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 + + @classmethod + def enabled(cls): + """Return backend enabled status by checking basic settings""" + return setting('BITBUCKET_CONSUMER_KEY') and setting('BITBUCKET_CONSUMER_SECRET') + +# Backend definition +BACKENDS = { + 'bitbucket': BitbucketAuth, +}