Ejemplo n.º 1
0
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
    }
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
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}
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
 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)
Ejemplo n.º 11
0
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
Ejemplo n.º 13
0
    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
Ejemplo n.º 14
0
    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)
Ejemplo n.º 15
0
    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)