From 08a9a2545cc99d739c191614ae800974098ffd5e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mat=C3=ADas=20Aguirre?= Date: Mon, 26 Sep 2011 13:24:14 -0300 Subject: [PATCH] Migrate Facebook to OAuth2. Closes gh-134 --- social_auth/backends/__init__.py | 14 +++++-- social_auth/backends/facebook.py | 69 +++++++++++++++----------------- 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/social_auth/backends/__init__.py b/social_auth/backends/__init__.py index db955aa..3cf23bb 100644 --- a/social_auth/backends/__init__.py +++ b/social_auth/backends/__init__.py @@ -674,14 +674,20 @@ class BaseOAuth2(BaseOAuth): """ AUTHORIZATION_URL = None ACCESS_TOKEN_URL = None + SCOPE_SEPARATOR = ' ' + RESPONSE_TYPE = 'code' def auth_url(self): """Return redirect url""" client_id, client_secret = self.get_key_and_secret() - args = {'client_id': client_id, - 'scope': ' '.join(self.get_scope()), - 'redirect_uri': self.redirect_uri, - 'response_type': 'code'} # requesting code + args = {'client_id': client_id, 'redirect_uri': self.redirect_uri} + + scope = self.get_scope() + if scope: + args['scope'] = self.SCOPE_SEPARATOR.join(self.get_scope()) + if self.RESPONSE_TYPE: + args['response_type'] = self.RESPONSE_TYPE + args.update(self.auth_extra_arguments()) return self.AUTHORIZATION_URL + '?' + urlencode(args) diff --git a/social_auth/backends/facebook.py b/social_auth/backends/facebook.py index b225223..90c6664 100644 --- a/social_auth/backends/facebook.py +++ b/social_auth/backends/facebook.py @@ -22,19 +22,16 @@ from django.conf import settings from django.utils import simplejson from django.contrib.auth import authenticate -from social_auth.backends import BaseOAuth, OAuthBackend, USERNAME +from social_auth.backends import BaseOAuth2, OAuthBackend, USERNAME from social_auth.utils import sanitize_log_data + # Facebook configuration -FACEBOOK_SERVER = 'graph.facebook.com' -FACEBOOK_AUTHORIZATION_URL = 'https://%s/oauth/authorize' % FACEBOOK_SERVER -FACEBOOK_ACCESS_TOKEN_URL = 'https://%s/oauth/access_token' % FACEBOOK_SERVER -FACEBOOK_CHECK_AUTH = 'https://%s/me' % FACEBOOK_SERVER EXPIRES_NAME = getattr(settings, 'SOCIAL_AUTH_EXPIRATION', 'expires') class FacebookBackend(OAuthBackend): - """Facebook OAuth authentication backend""" + """Facebook OAuth2 authentication backend""" name = 'facebook' # Default extra data to store EXTRA_DATA = [('id', 'id'), ('expires', EXPIRES_NAME)] @@ -48,23 +45,40 @@ class FacebookBackend(OAuthBackend): 'last_name': response.get('last_name', '')} -class FacebookAuth(BaseOAuth): - """Facebook OAuth mechanism""" + +class FacebookAuth(BaseOAuth2): + """Facebook OAuth2 support""" AUTH_BACKEND = FacebookBackend + RESPONSE_TYPE = None + SCOPE_SEPARATOR = ',' + AUTHORIZATION_URL = 'https://www.facebook.com/dialog/oauth' + SETTINGS_KEY_NAME = 'FACEBOOK_APP_ID' + SETTINGS_SECRET_NAME = 'FACEBOOK_API_SECRET' + + def get_scope(self): + return getattr(settings, 'FACEBOOK_EXTENDED_PERMISSIONS', []) - def auth_url(self): - """Returns redirect url""" - args = {'client_id': settings.FACEBOOK_APP_ID, - 'redirect_uri': self.redirect_uri} - if hasattr(settings, 'FACEBOOK_EXTENDED_PERMISSIONS'): - args['scope'] = ','.join(settings.FACEBOOK_EXTENDED_PERMISSIONS) - args.update(self.auth_extra_arguments()) - return FACEBOOK_AUTHORIZATION_URL + '?' + urlencode(args) + def user_data(self, access_token): + """Loads user data from service""" + params = {'access_token': access_token,} + url = 'https://graph.facebook.com/me?' + urlencode(params) + try: + data = simplejson.load(urlopen(url)) + logger.debug('Found user data for token %s', + sanitize_log_data(access_token), + extra=dict(data=data)) + return data + + except ValueError: + params.update({'access_token': sanitize_log_data(access_token)}) + logger.error('Could not load user data from Facebook.', + exc_info=True, extra=dict(data=params)) + return None def auth_complete(self, *args, **kwargs): - """Returns user, might be logged in""" + """Completes loging process, must return user instance""" if 'code' in self.data: - url = FACEBOOK_ACCESS_TOKEN_URL + '?' + \ + url = 'https://graph.facebook.com/oauth/access_token?' + \ urlencode({'client_id': settings.FACEBOOK_APP_ID, 'redirect_uri': self.redirect_uri, 'client_secret': settings.FACEBOOK_API_SECRET, @@ -81,29 +95,12 @@ class FacebookAuth(BaseOAuth): # premission was requested if 'expires' in response: data['expires'] = response['expires'][0] - kwargs.update({'response': data, FacebookBackend.name: True}) + kwargs.update({'response': data, self.AUTH_BACKEND.name: True}) return authenticate(*args, **kwargs) else: error = self.data.get('error') or 'unknown error' raise ValueError('Authentication error: %s' % error) - def user_data(self, access_token): - """Loads user data from service""" - params = {'access_token': access_token,} - url = FACEBOOK_CHECK_AUTH + '?' + urlencode(params) - try: - data = simplejson.load(urlopen(url)) - logger.debug('Found user data for token %s', - sanitize_log_data(access_token), - extra=dict(data=data)) - return data - - except ValueError: - params.update({'access_token': sanitize_log_data(access_token)}) - logger.error('Could not load user data from Facebook.', - exc_info=True, extra=dict(data=params)) - return None - @classmethod def enabled(cls): """Return backend enabled status by checking basic settings""" -- 2.39.5