def create_user(backend, details, response, uid, username, user=None, *args, **kwargs): """Create user. Depends on get_username pipeline.""" if user: return {"user": user} if not username: return None warn_setting("SOCIAL_AUTH_CREATE_USERS", "create_user") if not setting("SOCIAL_AUTH_CREATE_USERS", True): # Send signal for cases where tracking failed registering is useful. socialauth_not_registered.send(sender=backend.__class__, uid=uid, response=response, details=details) return None email = details.get("email") if EmailAddress.objects.filter(email=email): # TODO - Make this fail gracefully back to sign up message = ( "The email address provided by the external " "service is already associated with another account. Please " "log in to that account first and associate your account." ) raise AuthException(backend, message) else: user = User.objects.create_user(username=username, email=email) return { "user": user, "is_new": True }
def openid_request(self, extra_params=None): """Return openid request""" try: return self.consumer().begin( url_add_parameters(self.openid_url(), extra_params)) except DiscoveryFailure, err: raise AuthException(self, 'OpenID discovery error: %s' % err)
def auth_complete(self, *args, **kwargs): """Completes login process, must return user instance.""" if not users.get_current_user(): raise AuthException('Authentication error') # Setting these two are necessary for BaseAuth.authenticate to work kwargs.update({'response': '', self.AUTH_BACKEND.name: True}) return authenticate(*args, **kwargs)
def openid_request(self, extra_params=None): """Return openid request""" openid_url = self.openid_url() if extra_params: query = urlsplit(openid_url).query openid_url += (query and '&' or '?') + urlencode(extra_params) try: return self.consumer().begin(openid_url) except DiscoveryFailure, err: raise AuthException(self, 'OpenID discovery error: %s' % err)
def social_auth_user(backend, uid, user=None, *args, **kwargs): """Return UserSocialAuth account for backend/uid pair or None if it doesn't exists. Raise AuthException if UserSocialAuth entry belongs to another user. """ social_user = UserSocialAuth.get_social_auth(backend.name, uid) if social_user: if user and social_user.user != user: msg = ugettext('This %(provider)s account already in use.') raise AuthException(backend, msg % {'provider': backend.name}) elif not user: user = social_user.user return {'social_user': social_user, 'user': user}
def auth_complete(self, *args, **kwargs): """Completes loging process, must return user instance""" access_token = None response = self.response if 'code' in self.data: access_token = self.response['access_token'][0] if 'expires' in self._response: expires = self.response['expires'][0] if 'signed_request' in self.data: if response is not None: access_token = response.get('access_token') or \ response.get('oauth_token') or \ self.data.get('access_token') if 'expires' in self._response: expires = response['expires'] if access_token: data = self.user_data(access_token) if not isinstance(data, dict): # From time to time Facebook responds back a JSON with just # False as value, the reason is still unknown, but since the # data is needed (it contains the user ID used to identify the # account on further logins), this app cannot allow it to # continue with the auth process. raise AuthUnknownError( self, 'An error ocurred while ' 'retrieving users Facebook ' 'data') data['access_token'] = access_token # expires will not be part of response if offline access # premission was requested if expires: data['expires'] = expires kwargs.update({ 'auth': self, 'response': data, self.AUTH_BACKEND.name: True }) return authenticate(*args, **kwargs) else: if self.data.get('error') == 'access_denied': raise AuthCanceled(self) else: raise AuthException(self)
def auth_complete(self, *args, **kwargs): """Completes loging process, must return user instance""" access_token = None expires = None if 'code' in self.data: state = self.validate_state() url = ACCESS_TOKEN + urlencode({ 'client_id': backend_setting(self, self.SETTINGS_KEY_NAME), 'redirect_uri': self.get_redirect_uri(state), 'client_secret': backend_setting(self, self.SETTINGS_SECRET_NAME), 'code': self.data['code'] }) try: response = cgi.parse_qs(dsa_urlopen(url).read()) except HTTPError: raise AuthFailed( self, 'There was an error authenticating ' 'the app') access_token = response['access_token'][0] if 'expires' in response: expires = response['expires'][0] if 'signed_request' in self.data: response = load_signed_request( self.data.get('signed_request'), backend_setting(self, self.SETTINGS_SECRET_NAME)) if response is not None: access_token = response.get('access_token') or \ response.get('oauth_token') or \ self.data.get('access_token') if 'expires' in response: expires = response['expires'] if access_token: return self.do_auth(access_token, expires=expires, *args, **kwargs) else: if self.data.get('error') == 'access_denied': raise AuthCanceled(self) else: raise AuthException(self)
def associate_by_email(details, *args, **kwargs): """Return user entry with same email address as one returned on details.""" email = details.get('email') warn_setting('SOCIAL_AUTH_ASSOCIATE_BY_MAIL', 'associate_by_email') if email and setting('SOCIAL_AUTH_ASSOCIATE_BY_MAIL'): # try to associate accounts registered with the same email address, # only if it's a single object. AuthException is raised if multiple # objects are returned try: return {'user': User.objects.get(email=email)} except MultipleObjectsReturned: raise AuthException(kwargs['backend'], 'Not unique email address.') except User.DoesNotExist: pass
def associate_by_email(details, user=None, *args, **kwargs): """Return user entry with same email address as one returned on details.""" if user: return None email = details.get('email') if email: # try to associate accounts registered with the same email address, # only if it's a single object. AuthException is raised if multiple # objects are returned try: return {'user': UserSocialAuth.get_user_by_email(email=email)} except MultipleObjectsReturned: raise AuthException(kwargs['backend'], 'Not unique email address.') except ObjectDoesNotExist: pass
def auth_complete(self, *args, **kwargs): """Complete auth process""" response = self.consumer().complete(dict(self.data.items()), self.request.build_absolute_uri()) if not response: raise AuthException(self, 'OpenID relying party endpoint') elif response.status == SUCCESS: kwargs.update({ 'auth': self, 'response': response, self.AUTH_BACKEND.name: True }) return authenticate(*args, **kwargs) elif response.status == FAILURE: raise AuthFailed(self, response.message) elif response.status == CANCEL: raise AuthCanceled(self) else: raise AuthUnknownError(self, response.status)
def social_auth_user(backend, uid, user=None, *args, **kwargs): """Return UserSocialAuth account for backend/uid pair or None if it doesn't exists. Raise AuthException if UserSocialAuth entry belongs to another user. """ try: social_user = UserSocialAuth.objects.select_related('user')\ .get(provider=backend.name, uid=uid) except UserSocialAuth.DoesNotExist: social_user = None if social_user: if user and social_user.user != user: raise AuthException(backend, 'Account already in use.') elif not user: user = social_user.user return {'social_user': social_user, 'user': user}
def associate_by_email(details, user=None, *args, **kwargs): """Return user entry with same email address as one returned on details.""" if user: return None email = details.get('email') # Don't spam with a warning, this doesn't apply when providers check emails #warn_setting('SOCIAL_AUTH_ASSOCIATE_BY_MAIL', 'associate_by_email') if email and setting('SOCIAL_AUTH_ASSOCIATE_BY_MAIL', False): # try to associate accounts registered with the same email address, # only if it's a single object. AuthException is raised if multiple # objects are returned try: return {'user': UserSocialAuth.get_user_by_email(email=email)} except MultipleObjectsReturned: raise AuthException(kwargs['backend'], 'Not unique email address.') except ObjectDoesNotExist: pass
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.get('error'): error = data['error'] msg = error.get('error_msg', 'Unknown error') if error.get('error_code') == 5: raise AuthTokenRevoked(self, msg) else: raise AuthException(self, msg) if data: data = data.get('response')[0] data['user_photo'] = data.get('photo') # Backward compatibility return data
def auth_complete(self, *args, **kwargs): """Completes loging process, must return user instance""" if 'code' not in self.data: if self.data.get('error') == 'access_denied': raise AuthCanceled(self) else: raise AuthException(self) url = ACCESS_TOKEN + urlencode( { 'client_id': setting('FACEBOOK_APP_ID'), 'redirect_uri': self.redirect_uri, 'client_secret': setting('FACEBOOK_API_SECRET'), 'code': self.data['code'] }) try: response = cgi.parse_qs(urlopen(url).read()) except HTTPError: raise AuthFailed(self, 'There was an error authenticating the app') access_token = response['access_token'][0] data = self.user_data(access_token) if data is not None: data['access_token'] = access_token # expires will not be part of response if offline access # premission was requested if 'expires' in response: data['expires'] = response['expires'][0] kwargs.update({ 'auth': self, 'response': data, self.AUTH_BACKEND.name: True }) return authenticate(*args, **kwargs)
def auth_complete(self, *args, **kwargs): """Completes loging process, must return user instance""" access_token = None expires = None if 'code' in self.data: state = self.validate_state() url = ACCESS_TOKEN + urlencode( { 'client_id': setting('FACEBOOK_APP_ID'), 'redirect_uri': self.get_redirect_uri(state), 'client_secret': setting('FACEBOOK_API_SECRET'), 'code': self.data['code'] }) try: response = cgi.parse_qs(urlopen(url).read()) except HTTPError: raise AuthFailed(self, 'There was an error authenticating ' \ 'the app') access_token = response['access_token'][0] if 'expires' in response: expires = response['expires'][0] if 'signed_request' in self.data: response = load_signed_request(self.data.get('signed_request')) if response is not None: access_token = response.get('access_token') or \ response.get('oauth_token') or \ self.data.get('access_token') if 'expires' in response: expires = response['expires'] if access_token: data = self.user_data(access_token) if not isinstance(data, dict): # From time to time Facebook responds back a JSON with just # False as value, the reason is still unknown, but since the # data is needed (it contains the user ID used to identify the # account on further logins), this app cannot allow it to # continue with the auth process. raise AuthUnknownError(self, 'An error ocurred while ' \ 'retrieving users Facebook ' \ 'data') data['access_token'] = access_token # expires will not be part of response if offline access # premission was requested if expires: data['expires'] = expires kwargs.update({ 'auth': self, 'response': data, self.AUTH_BACKEND.name: True }) return authenticate(*args, **kwargs) else: if self.data.get('error') == 'access_denied': raise AuthCanceled(self) else: raise AuthException(self)