def oauth_request(self, token, url, extra_params=None): extra_params = extra_params or {} scope = GOOGLE_OAUTH_SCOPE + setting('GOOGLE_OAUTH_EXTRA_SCOPE', []) extra_params.update({ 'scope': ' '.join(scope), }) if not self.registered(): xoauth_displayname = setting('GOOGLE_DISPLAY_NAME', 'Social Auth') extra_params['xoauth_displayname'] = xoauth_displayname return super(GoogleOAuth, self).oauth_request(token, url, extra_params)
def save_status_to_session(request, auth, pipeline_index, *args, **kwargs): """Saves current social-auth status to session.""" next_entry = setting('SOCIAL_AUTH_PIPELINE_RESUME_ENTRY') if next_entry and next_entry in PIPELINE: idx = PIPELINE.index(next_entry) else: idx = pipeline_index + 1 data = auth.to_session_dict(idx, *args, **kwargs) name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline') request.session[name] = data
def validate_whitelists(backend, email): """ Validates allowed domains and emails against the following settings: GOOGLE_WHITE_LISTED_DOMAINS GOOGLE_WHITE_LISTED_EMAILS All domains and emails are allowed if setting is an empty list. """ emails = setting('GOOGLE_WHITE_LISTED_EMAILS', []) domains = setting('GOOGLE_WHITE_LISTED_DOMAINS', []) if emails and email in emails: return # you're good if domains and email.split('@', 1)[1] not in domains: raise AuthFailed(backend, 'Domain not allowed')
class YahooOAuthBackend(OAuthBackend): """Yahoo OAuth authentication backend""" name = 'yahoo-oauth' EXTRA_DATA = [ ('guid', 'id'), ('access_token', 'access_token'), ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires')) ] def get_user_id(self, details, response): return response['guid'] def get_user_details(self, response): """Return user details from Yahoo Profile""" fname = response.get('givenName') lname = response.get('familyName') if 'emails' in response: email = response.get('emails')[0]['handle'] else: email = '' return {USERNAME: response.get('nickname'), 'email': email, 'fullname': '%s %s' % (fname, lname), 'first_name': fname, 'last_name': lname}
def get_backends(force_load=False): """ Entry point to the BACKENDS cache. If BACKENDSCACHE hasn't been populated, each of the modules referenced in AUTHENTICATION_BACKENDS is imported and checked for a BACKENDS definition and if enabled, added to the cache. Previously all backends were attempted to be loaded at import time of this module, which meant that backends that subclass bases found in this module would not have the chance to be loaded by the time they were added to this module's BACKENDS dict. See: https://github.com/omab/django-social-auth/issues/204 This new approach ensures that backends are allowed to subclass from bases in this module and still be picked up. A force_load boolean arg is also provided so that get_backend below can retry a requested backend that may not yet be discovered. """ if not BACKENDSCACHE or force_load: for auth_backend in setting('AUTHENTICATION_BACKENDS'): mod, cls_name = auth_backend.rsplit('.', 1) module = import_module(mod) backend = getattr(module, cls_name) if issubclass(backend, SocialAuthBackend): name = backend.name backends = getattr(module, 'BACKENDS', {}) if name in backends and backends[name].enabled(): BACKENDSCACHE[name] = backends[name] return BACKENDSCACHE
def auth_extra_arguments(self): """Return extra arguments needed on auth process, setting is per backend and defined by: <backend name in uppercase>_AUTH_EXTRA_ARGUMENTS. """ backend_name = self.AUTH_BACKEND.name.upper().replace('-', '_') return setting(backend_name + '_AUTH_EXTRA_ARGUMENTS', {})
def request_token_extra_arguments(self): """Return extra arguments needed on request-token process, setting is per backend and defined by: <backend name in uppercase>_REQUEST_TOKEN_EXTRA_ARGUMENTS. """ backend_name = self.AUTH_BACKEND.name.upper().replace('-', '_') return setting(backend_name + '_REQUEST_TOKEN_EXTRA_ARGUMENTS', {})
class YaruBackend(OAuthBackend): """Yandex OAuth authentication backend""" name = 'yaru' EXTRA_DATA = [ ('id', 'id'), ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires')) ] def get_user_details(self, response): """Return user details from Yandex account""" name = response['name'] last_name = '' if ' ' in name: names = name.split(' ') last_name = names[0] first_name = names[1] else: first_name = name return { USERNAME: get_username_from_url(response.get('links')), 'email': response.get('email', ''), 'first_name': first_name, 'last_name': last_name, }
def get_user_id(self, details, response): """Use google email or id as unique id""" user_id = super(GoogleOAuth2Backend, self).get_user_id(details, response) if setting('GOOGLE_OAUTH2_USE_UNIQUE_USER_ID', False): return response['id'] return user_id
class EvernoteBackend(OAuthBackend): """ Evernote OAuth authentication backend. Possible Values: {'edam_expires': ['1367525289541'], 'edam_noteStoreUrl': [ 'https://sandbox.evernote.com/shard/s1/notestore' ], 'edam_shard': ['s1'], 'edam_userId': ['123841'], 'edam_webApiUrlPrefix': ['https://sandbox.evernote.com/shard/s1/'], 'oauth_token': [ 'S=s1:U=1e3c1:E=13e66dbee45:C=1370f2ac245:P=185:A=my_user:'******'H=411443c5e8b20f8718ed382a19d4ae38' ]} """ name = 'evernote' EXTRA_DATA = [('access_token', 'access_token'), ('oauth_token', 'oauth_token'), ('edam_noteStoreUrl', 'store_url'), ('edam_expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))] def get_user_details(self, response): """Return user details from Evernote account""" return { USERNAME: response['edam_userId'], 'email': '', } def get_user_id(self, details, response): return response['edam_userId']
def auth_complete(self, *args, **kwargs): """Performs check of authentication in VKontakte, returns User if succeeded""" app_cookie = 'vk_app_' + self.APP_ID if not 'id' in self.request.GET or \ not app_cookie in self.request.COOKIES: raise ValueError('VKontakte authentication is not completed') cookie_dict = dict( item.split('=') for item in self.request.COOKIES[app_cookie].split('&')) check_str = ''.join(item + '=' + cookie_dict[item] for item in ['expire', 'mid', 'secret', 'sid']) hash = md5(check_str + setting('VKONTAKTE_APP_SECRET')).hexdigest() if hash != cookie_dict['sig'] or int(cookie_dict['expire']) < time(): raise ValueError('VKontakte authentication failed: invalid hash') else: kwargs.update({ 'auth': self, 'response': self.user_data(cookie_dict['mid']), self.AUTH_BACKEND.name: True }) return authenticate(*args, **kwargs)
def expiration_datetime(self): """Return provider session live seconds. Returns a timedelta ready to use with session.set_expiry(). If provider returns a timestamp instead of session seconds to live, the timedelta is inferred from current time (using UTC timezone). None is returned if there's no value stored or it's invalid. """ name = setting('SOCIAL_AUTH_EXPIRATION', 'expires') if self.extra_data and name in self.extra_data: try: expires = int(self.extra_data.get(name)) except (ValueError, TypeError): return None now = datetime.now() now_timestamp = time.mktime(now.timetuple()) # Detect if expires is a timestamp if expires > now_timestamp: # expires is a datetime return datetime.utcfromtimestamp(expires) \ .replace(tzinfo=utc) - \ now.replace(tzinfo=utc) else: # expires is a timedelta return timedelta(seconds=expires)
def extra_data(self, user, uid, response, details): """Return defined extra data names to store in extra_data field. Settings will be inspected to get more values names that should be stored on extra_data field. Setting name is created from current backend name (all uppercase) plus _SREG_EXTRA_DATA and _AX_EXTRA_DATA because values can be returned by SimpleRegistration or AttributeExchange schemas. Both list must be a value name and an alias mapping similar to SREG_ATTR, OLD_AX_ATTRS or AX_SCHEMA_ATTRS """ name = self.name.replace('-', '_').upper() sreg_names = setting(name + '_SREG_EXTRA_DATA') ax_names = setting(name + '_AX_EXTRA_DATA') data = self.values_from_response(response, sreg_names, ax_names) return data
class LiveBackend(OAuthBackend): name = 'live' EXTRA_DATA = [ ('id', 'id'), ('access_token', 'access_token'), ('reset_token', 'reset_token'), ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires')), ('email', 'email'), ('first_name', 'first_name'), ('last_name', 'last_name'), ] def get_user_id(self, details, response): return response['id'] def get_user_details(self, response): """Return user details from Live Connect account""" try: email = response['emails']['account'] except KeyError: email = '' return { USERNAME: response.get('name'), 'email': email, 'first_name': response.get('first_name'), 'last_name': response.get('last_name') }
def auth_complete(self, *args, **kwargs): """Performs check of authentication in VKontakte, returns User if succeeded""" app_cookie = 'vk_app_' + self.APP_ID if not 'id' in self.request.GET or \ not app_cookie in self.request.COOKIES: raise ValueError('VKontakte authentication is not completed') cookie_dict = dict(item.split('=') for item in self.request.COOKIES[app_cookie].split('&')) check_str = ''.join(item + '=' + cookie_dict[item] for item in ['expire', 'mid', 'secret', 'sid']) hash = md5(check_str + setting('VKONTAKTE_APP_SECRET')).hexdigest() if hash != cookie_dict['sig'] or int(cookie_dict['expire']) < time(): raise ValueError('VKontakte authentication failed: invalid hash') else: kwargs.update({ 'auth': self, 'response': self.user_data(cookie_dict['mid']), self.AUTH_BACKEND.name: True }) return authenticate(*args, **kwargs)
def build_absolute_uri(self, path=None): """Build absolute URI for given path. Replace http:// schema with https:// if SOCIAL_AUTH_REDIRECT_IS_HTTPS is defined. """ uri = self.request.build_absolute_uri(path) if setting('SOCIAL_AUTH_REDIRECT_IS_HTTPS'): uri = uri.replace('http://', 'https://') return uri
def user_data(self, access_token, *args, **kwargs): """Loads user data from Orkut service""" fields = ORKUT_DEFAULT_DATA if setting('ORKUT_EXTRA_DATA'): fields += ',' + setting('ORKUT_EXTRA_DATA') scope = ORKUT_SCOPE + setting('ORKUT_EXTRA_SCOPE', []) params = {'method': 'people.get', 'id': 'myself', 'userId': '@me', 'groupId': '@self', 'fields': fields, 'scope': ' '.join(scope)} request = self.oauth_request(access_token, ORKUT_REST_ENDPOINT, params) response = dsa_urlopen(request.to_url()).read() try: return simplejson.loads(response)['data'] except (ValueError, KeyError): return None
def user_data(self, access_token, *args, **kwargs): """Loads user data from Orkut service""" fields = ORKUT_DEFAULT_DATA if setting('ORKUT_EXTRA_DATA'): fields += ',' + setting('ORKUT_EXTRA_DATA') scope = ORKUT_SCOPE + setting('ORKUT_EXTRA_SCOPE', []) params = { 'method': 'people.get', 'id': 'myself', 'userId': '@me', 'groupId': '@self', 'fields': fields, 'scope': ' '.join(scope) } request = self.oauth_request(access_token, ORKUT_REST_ENDPOINT, params) response = dsa_urlopen(request.to_url()).read() try: return simplejson.loads(response)['data'] except (ValueError, KeyError): return None
def extra_data(self, user, uid, response, details): """Return users extra data""" # BrowserID sends timestamp for expiration date, here we # comvert it to the remaining seconds expires = (response['expires'] / 1000) - \ time.mktime(datetime.now().timetuple()) return { 'audience': response['audience'], 'issuer': response['issuer'], setting('SOCIAL_AUTH_EXPIRATION', 'expires'): expires }
def user_data(self, access_token, *args, **kwargs): """Return user data provided""" fields_selectors = LINKEDIN_FIELD_SELECTORS + \ setting('LINKEDIN_EXTRA_FIELD_SELECTORS', []) url = LINKEDIN_CHECK_AUTH + ':(%s)' % ','.join(fields_selectors) request = self.oauth_request(access_token, url) raw_xml = self.fetch_response(request) try: return to_dict(ElementTree.fromstring(raw_xml)) except (ExpatError, KeyError, IndexError): return None
class VKontakteAuth(BaseAuth): """VKontakte OpenAPI authorization mechanism""" AUTH_BACKEND = VKontakteBackend APP_ID = setting('VKONTAKTE_APP_ID') def user_data(self, access_token, *args, **kwargs): return dict(self.request.GET) def auth_html(self): """Returns local VK authentication page, not necessary for VK to authenticate. """ from django.template import RequestContext, loader dict = {'VK_APP_ID': self.APP_ID, 'VK_COMPLETE_URL': self.redirect} vk_template = loader.get_template(LOCAL_HTML) context = RequestContext(self.request, dict) return vk_template.render(context) def auth_complete(self, *args, **kwargs): """Performs check of authentication in VKontakte, returns User if succeeded""" app_cookie = 'vk_app_' + self.APP_ID if not 'id' in self.request.GET or \ not app_cookie in self.request.COOKIES: raise ValueError('VKontakte authentication is not completed') cookie_dict = dict( item.split('=') for item in self.request.COOKIES[app_cookie].split('&')) check_str = ''.join(item + '=' + cookie_dict[item] for item in ['expire', 'mid', 'secret', 'sid']) hash = md5(check_str + setting('VKONTAKTE_APP_SECRET')).hexdigest() if hash != cookie_dict['sig'] or int(cookie_dict['expire']) < time(): raise ValueError('VKontakte authentication failed: invalid hash') else: kwargs.update({ 'auth': self, 'response': self.user_data(cookie_dict['mid']), self.AUTH_BACKEND.name: True }) return authenticate(*args, **kwargs) @property def uses_redirect(self): """VKontakte does not require visiting server url in order to do authentication, so auth_xxx methods are not needed to be called. Their current implementation is just an example""" return False
def user_data(self, access_token, response, *args, **kwargs): """Loads user data from service""" fields = ','.join(VK_DEFAULT_DATA + setting('VK_EXTRA_DATA', [])) params = {'access_token': access_token, 'fields': fields, 'uids': response.get('user_id')} data = vkontakte_api('users.get', params) if data: data = data.get('response')[0] data['user_photo'] = data.get('photo') # Backward compatibility return data
class FlickrBackend(OAuthBackend): """Flickr OAuth authentication backend""" name = 'flickr' # Default extra data to store EXTRA_DATA = [('id', 'id'), ('username', 'username'), ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))] def get_user_details(self, response): """Return user details from Flickr account""" return { USERNAME: response.get('id'), 'email': '', 'first_name': response.get('fullname') }
class GithubBackend(OAuthBackend): """Github OAuth authentication backend""" name = 'github' # Default extra data to store EXTRA_DATA = [ ('id', 'id'), ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires')) ] def get_user_details(self, response): """Return user details from Github account""" return {USERNAME: response.get('login'), 'email': response.get('email') or '', 'first_name': response.get('name')}
def load_signed_request(signed_request, api_secret=None): try: sig, payload = signed_request.split(u".", 1) sig = base64_url_decode(sig) data = simplejson.loads(base64_url_decode(payload)) expected_sig = hmac.new( api_secret or setting("FACEBOOK_API_SECRET"), msg=payload, digestmod=hashlib.sha256 ).digest() # allow the signed_request to function for upto 1 day if sig == expected_sig and data[u"issued_at"] > (time.time() - 86400): return data except ValueError: pass # ignore if can't split on dot
def update_user_details(backend, details, response, user, is_new=False, *args, **kwargs): """Update user details using data from provider.""" changed = False # flag to track changes for name, value in details.iteritems(): # do not update username, it was already generated # do not update configured fields if user already existed if name in (USERNAME, 'id', 'pk') or (not is_new and name in setting( 'SOCIAL_AUTH_PROTECTED_USER_FIELDS', [])): continue if value and value != getattr(user, name, None): setattr(user, name, value) changed = True # Fire a pre-update signal sending current backend instance, # user instance (created or retrieved from database), service # response and processed details. # # Also fire socialauth_registered signal for newly registered # users. # # Signal handlers must return True or False to signal instance # changes. Send method returns a list of tuples with receiver # and it's response. signal_response = lambda (receiver, response): response signal_kwargs = { 'sender': backend.__class__, 'user': user, 'response': response, 'details': details } changed |= any(filter(signal_response, pre_update.send(**signal_kwargs))) # Fire socialauth_registered signal on new user registration if is_new: changed |= any( filter(signal_response, socialauth_registered.send(**signal_kwargs))) if changed: user.save()
def load_signed_request(signed_request, api_secret=None): try: sig, payload = signed_request.split(u'.', 1) sig = base64_url_decode(sig) data = simplejson.loads(base64_url_decode(payload)) expected_sig = hmac.new(api_secret or setting('FACEBOOK_API_SECRET'), msg=payload, digestmod=hashlib.sha256).digest() # allow the signed_request to function for upto 1 day if sig == expected_sig and \ data[u'issued_at'] > (time.time() - 86400): return data except ValueError: pass # ignore if can't split on dot
def user_data(self, access_token, response, *args, **kwargs): """Loads user data from service""" fields = ','.join(VK_DEFAULT_DATA + setting('VK_EXTRA_DATA', [])) params = { 'access_token': access_token, 'fields': fields, 'uids': response.get('user_id') } data = vkontakte_api('users.get', params) if data: data = data.get('response')[0] data['user_photo'] = data.get('photo') # Backward compatibility return data
def auth_process(request, backend): """Authenticate using social backend""" # Save any defined next value into session data = request.POST if request.method == 'POST' else request.GET if REDIRECT_FIELD_NAME in data: # Check and sanitize a user-defined GET/POST next field value redirect = data[REDIRECT_FIELD_NAME] if setting('SOCIAL_AUTH_SANITIZE_REDIRECTS', True): redirect = sanitize_redirect(request.get_host(), redirect) request.session[REDIRECT_FIELD_NAME] = redirect or DEFAULT_REDIRECT # Clean any partial pipeline info before starting the process clean_partial_pipeline(request) if backend.uses_redirect: return HttpResponseRedirect(backend.auth_url()) else: return HttpResponse(backend.auth_html(), content_type='text/html;charset=UTF-8')
class DropboxBackend(OAuthBackend): """Dropbox OAuth authentication backend""" name = 'dropbox' # Default extra data to store EXTRA_DATA = [('id', 'id'), ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))] def get_user_details(self, response): """Return user details from Dropbox account""" return { USERNAME: str(response.get('uid')), 'email': response.get('email'), 'first_name': response.get('display_name') } def get_user_id(self, details, response): """OAuth providers return an unique user id in response""" # Dropbox uses a uid parameter instead of id like most others... return response['uid']
class VKontakteOAuth2Backend(OAuthBackend): """VKontakteOAuth2 authentication backend""" name = 'vkontakte-oauth2' EXTRA_DATA = [('id', 'id'), ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))] def get_user_id(self, details, response): """OAuth providers return an unique user id in response""" return response['user_id'] def get_user_details(self, response): """Return user details from Vkontakte account""" return { USERNAME: response.get('screen_name'), 'email': '', 'first_name': response.get('first_name'), 'last_name': response.get('last_name') }
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
def extra_data(self, user, uid, response, details): """Return access_token and extra defined names to store in extra_data field""" data = {'access_token': response.get('access_token', '')} name = self.name.replace('-', '_').upper() names = (self.EXTRA_DATA or []) + setting(name + '_EXTRA_DATA', []) for entry in names: if len(entry) == 2: (name, alias), discard = entry, False elif len(entry) == 3: name, alias, discard = entry elif len(entry) == 1: name = alias = entry else: # ??? continue value = response.get(name) if discard and not value: continue data[alias] = value return data
def update_user_details(backend, details, response, user, is_new=False, *args, **kwargs): """Update user details using data from provider.""" changed = False # flag to track changes for name, value in details.iteritems(): # do not update username, it was already generated # do not update configured fields if user already existed if name in (USERNAME, 'id', 'pk') or (not is_new and name in setting('SOCIAL_AUTH_PROTECTED_USER_FIELDS', [])): continue if value and value != getattr(user, name, None): setattr(user, name, value) changed = True # Fire a pre-update signal sending current backend instance, # user instance (created or retrieved from database), service # response and processed details. # # Also fire socialauth_registered signal for newly registered # users. # # Signal handlers must return True or False to signal instance # changes. Send method returns a list of tuples with receiver # and it's response. signal_response = lambda (receiver, response): response signal_kwargs = {'sender': backend.__class__, 'user': user, 'response': response, 'details': details} changed |= any(filter(signal_response, pre_update.send(**signal_kwargs))) # Fire socialauth_registered signal on new user registration if is_new: changed |= any(filter(signal_response, socialauth_registered.send(**signal_kwargs))) if changed: user.save()
class GoogleOAuth2Backend(GoogleOAuthBackend): """Google OAuth2 authentication backend""" name = 'google-oauth2' EXTRA_DATA = [('refresh_token', 'refresh_token', True), ('expires_in', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))] def get_user_id(self, details, response): """Use google email or id as unique id""" user_id = super(GoogleOAuth2Backend, self).get_user_id(details, response) if setting('GOOGLE_OAUTH2_USE_UNIQUE_USER_ID', False): return response['id'] return user_id def get_user_details(self, response): email = response.get('email', '') return { USERNAME: email.split('@', 1)[0], 'email': email, 'fullname': response.get('name', ''), 'first_name': response.get('given_name', ''), 'last_name': response.get('family_name', '') }
BaseOAuth2, USERNAME from core.social_auth.utils import setting, log, dsa_urlopen # Vkontakte configuration VK_AUTHORIZATION_URL = 'http://oauth.vk.com/authorize' VK_ACCESS_TOKEN_URL = 'https://oauth.vk.com/access_token' VK_SERVER = 'vk.com' VK_DEFAULT_DATA = ['first_name', 'last_name', 'screen_name', 'nickname', 'photo'] VKONTAKTE_API_URL = 'https://api.vkontakte.ru/method/' VKONTAKTE_SERVER_API_URL = 'http://api.vkontakte.ru/api.php' VKONTAKTE_API_VERSION = '3.0' USE_APP_AUTH = setting('VKONTAKTE_APP_AUTH', False) LOCAL_HTML = setting('VKONTAKTE_LOCAL_HTML', 'vkontakte.html') class VKontakteBackend(SocialAuthBackend): """VKontakte OpenAPI authentication backend""" name = 'vkontakte' def get_user_id(self, details, response): """Return user unique id provided by VKontakte""" return response['id'] def get_user_details(self, response): """Return user details from VKontakte request""" nickname = response.get('nickname') or '' return {
from core.social_auth.db.base import UserSocialAuthMixin, AssociationMixin, \ NonceMixin from core.social_auth.fields import JSONField from core.social_auth.utils import setting from django.contrib.auth.models import User # If User class is overridden, it *must* provide the following fields # and methods work with django-social-auth: # # username = CharField() # last_login = DateTimeField() # is_active = BooleanField() # def is_authenticated(): # ... if setting('SOCIAL_AUTH_USER_MODEL'): UserModel = models.get_model(*setting('SOCIAL_AUTH_USER_MODEL') .rsplit('.', 1)) else: from django.contrib.auth.models import User as UserModel class UserSocialAuth(models.Model, UserSocialAuthMixin): """Social Auth association model""" User = UserModel user = models.ForeignKey(UserModel, related_name='social_auth') provider = models.CharField(max_length=32) uid = models.CharField(max_length=255) extra_data = JSONField(default='{}') class Meta:
""" import os.path, urllib2, core from django.http import HttpResponseRedirect, HttpResponse from django.contrib.auth import login, REDIRECT_FIELD_NAME from django.contrib.auth.decorators import login_required from django.contrib import messages from django.views.decorators.csrf import csrf_exempt from core.social_auth.utils import sanitize_redirect, setting, \ backend_setting, clean_partial_pipeline from core.social_auth.decorators import dsa_view DEFAULT_REDIRECT = setting('SOCIAL_AUTH_LOGIN_REDIRECT_URL') or \ setting('LOGIN_REDIRECT_URL') LOGIN_ERROR_URL = setting('LOGIN_ERROR_URL', setting('LOGIN_URL')) PIPELINE_KEY = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline') @dsa_view(setting('SOCIAL_AUTH_COMPLETE_URL_NAME', 'socialauth_complete')) def auth(request, backend): """Start authentication process""" return auth_process(request, backend) @csrf_exempt @dsa_view() def complete(request, backend, *args, **kwargs): """Authentication complete view, override this view if transaction
return super(GoogleOAuth, cls).get_key_and_secret() except AttributeError: return 'anonymous', 'anonymous' @classmethod def enabled(cls): """Google OAuth is always enabled because of anonymous access""" return True def registered(self): """Check if Google OAuth Consumer Key and Consumer Secret are set""" return self.get_key_and_secret() != ('anonymous', 'anonymous') # TODO: Remove this setting name check, keep for backward compatibility _OAUTH2_KEY_NAME = setting('GOOGLE_OAUTH2_CLIENT_ID') and \ 'GOOGLE_OAUTH2_CLIENT_ID' or \ 'GOOGLE_OAUTH2_CLIENT_KEY' class GoogleOAuth2(BaseOAuth2): """Google OAuth2 support""" AUTH_BACKEND = GoogleOAuth2Backend AUTHORIZATION_URL = 'https://accounts.google.com/o/oauth2/auth' ACCESS_TOKEN_URL = 'https://accounts.google.com/o/oauth2/token' SETTINGS_KEY_NAME = _OAUTH2_KEY_NAME SETTINGS_SECRET_NAME = 'GOOGLE_OAUTH2_CLIENT_SECRET' SCOPE_VAR_NAME = 'GOOGLE_OAUTH_EXTRA_SCOPE' DEFAULT_SCOPE = GOOGLE_OAUTH2_SCOPE REDIRECT_STATE = False
def complete_process(request, backend, *args, **kwargs): """Authentication complete process""" # pop redirect value before the session is trashed on login() redirect_value = request.session.get(REDIRECT_FIELD_NAME, '') user = auth_complete(request, backend, *args, **kwargs) if isinstance(user, HttpResponse): return user if not user and request.user.is_authenticated(): return HttpResponseRedirect(redirect_value) if user: # copy the profile image if user.social_user.provider == 'facebook': picture_page = "https://graph.facebook.com/"+user.username+"/picture?type=square" if user.social_user.provider == 'twitter': picture_page = "http://api.twitter.com/1/users/profile_image?screen_name="+user.username+"&size=normal" if user.social_user.provider == 'yahoo': picture_page = "http://img.msg.yahoo.com/avatar.php?yids="+user.username if user.social_user.provider == 'google': picture_page = None if picture_page: opener1 = urllib2.build_opener() page1 = opener1.open(picture_page) my_picture = page1.read() filename = core.__path__[0] + '/static/photos/profile/'+ user.username fout = open(filename, "wb") fout.write(my_picture) fout.close() if getattr(user, 'is_active', True): # catch is_new flag before login() might reset the instance is_new = getattr(user, 'is_new', False) login(request, user) # user.social_user is the used UserSocialAuth instance defined # in authenticate process social_user = user.social_user if redirect_value: request.session[REDIRECT_FIELD_NAME] = redirect_value or \ DEFAULT_REDIRECT if setting('SOCIAL_AUTH_SESSION_EXPIRATION', True): # Set session expiration date if present and not disabled by # setting. Use last social-auth instance for current provider, # users can associate several accounts with a same provider. expiration = social_user.expiration_datetime() if expiration: try: request.session.set_expiry(expiration) except OverflowError: # Handle django time zone overflow, set default expiry. request.session.set_expiry(None) # store last login backend name in session key = setting('SOCIAL_AUTH_LAST_LOGIN', 'social_auth_last_login_backend') request.session[key] = social_user.provider # Remove possible redirect URL from session, if this is a new # account, send him to the new-users-page if defined. new_user_redirect = backend_setting(backend, 'SOCIAL_AUTH_NEW_USER_REDIRECT_URL') if new_user_redirect and is_new: url = new_user_redirect else: url = redirect_value or \ backend_setting(backend, 'SOCIAL_AUTH_LOGIN_REDIRECT_URL') or \ DEFAULT_REDIRECT else: url = backend_setting(backend, 'SOCIAL_AUTH_INACTIVE_USER_URL', LOGIN_ERROR_URL) else: msg = setting('LOGIN_ERROR_MESSAGE', None) if msg: messages.error(request, msg) url = backend_setting(backend, 'LOGIN_ERROR_URL', LOGIN_ERROR_URL) return HttpResponse("<script type='text/javascript'> window.close(); window.opener.refreshPage(); </script>");
def get_scope(self): return setting(VKontakteOAuth2.SCOPE_VAR_NAME) or \ setting('VKONTAKTE_OAUTH2_EXTRA_SCOPE')
def _api_get_val_fun(name, conf): if USE_APP_AUTH: return USE_APP_AUTH.get(name) else: return setting(conf)
from functools import wraps from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect, HttpResponseServerError from django.utils.importlib import import_module from core.social_auth.backends import get_backend from core.social_auth.utils import setting, log, backend_setting LOGIN_ERROR_URL = setting("LOGIN_ERROR_URL", setting("LOGIN_URL")) PROCESS_EXCEPTIONS = setting("SOCIAL_AUTH_PROCESS_EXCEPTIONS", "core.social_auth.utils.log_exceptions_to_messages") def dsa_view(redirect_name=None): """Decorate djangos-social-auth views. Will check and retrieve backend or return HttpResponseServerError if backend is not found. redirect_name parameter is used to build redirect URL used by backend. """ def dec(func): @wraps(func) def wrapper(request, backend, *args, **kwargs): if redirect_name: redirect = reverse(redirect_name, args=(backend,)) else: redirect = request.path backend = get_backend(backend, request, redirect) if not backend:
def wrapper(request, backend, *args, **kwargs): if redirect_name: redirect = reverse(redirect_name, args=(backend,)) else: redirect = request.path backend = get_backend(backend, request, redirect) if not backend: return HttpResponseServerError("Incorrect authentication " + "service") RAISE_EXCEPTIONS = backend_setting(backend, "SOCIAL_AUTH_RAISE_EXCEPTIONS", setting("DEBUG")) try: return func(request, backend, *args, **kwargs) except Exception, e: # some error ocurred if RAISE_EXCEPTIONS: raise log("error", unicode(e), exc_info=True, extra={"request": request}) url = None mod, func_name = PROCESS_EXCEPTIONS.rsplit(".", 1) try: process = getattr(import_module(mod), func_name, lambda *args: None) except ImportError: pass else: url = process(request, backend, e) if not url: url = backend_setting(backend, "SOCIAL_AUTH_BACKEND_ERROR_URL", LOGIN_ERROR_URL) return HttpResponseRedirect(url)
""" from urllib2 import HTTPError try: from urlparse import parse_qs parse_qs # placate pyflakes except ImportError: # fall back for Python 2.5 from cgi import parse_qs from oauth2 import Token from core.social_auth.utils import setting from core.social_auth.backends import ConsumerBasedOAuth, OAuthBackend, USERNAME, \ exceptions if setting('EVERNOTE_DEBUG', False): EVERNOTE_SERVER = 'sandbox.evernote.com' else: EVERNOTE_SERVER = 'www.evernote.com' EVERNOTE_REQUEST_TOKEN_URL = 'https://%s/oauth' % EVERNOTE_SERVER EVERNOTE_ACCESS_TOKEN_URL = 'https://%s/oauth' % EVERNOTE_SERVER EVERNOTE_AUTHORIZATION_URL = 'https://%s/OAuth.action' % EVERNOTE_SERVER class EvernoteBackend(OAuthBackend): """ Evernote OAuth authentication backend. Possible Values: {'edam_expires': ['1367525289541'],
def enabled(cls): """Return backend enabled status by checking basic settings""" return setting('DROPBOX_APP_ID') and setting('DROPBOX_API_SECRET')