Ejemplo n.º 1
0
def signin(request):
    """
    signin page. It manages the legacy authentification (user/password) 
    and openid authentification
    
    url: /signin/
    
    template : authopenid/signin.htm
    """
    logging.debug('in signin view')
    on_failure = signin_failure
    email_feeds_form = askbot_forms.SimpleEmailSubscribeForm()

    next_url = get_next_url(request)
    logging.debug('next url is %s' % next_url)

    if askbot_settings.ALLOW_ADD_REMOVE_LOGIN_METHODS == False \
        and request.user.is_authenticated():
        return HttpResponseRedirect(next_url)

    if next_url == reverse('user_signin'):
        next_url = '%(next)s?next=%(next)s' % {'next': next_url}

    login_form = forms.LoginForm(initial = {'next': next_url})

    #todo: get next url make it sticky if next is 'user_signin'
    if request.method == 'POST':

        login_form = forms.LoginForm(request.POST)
        if login_form.is_valid():

            provider_name = login_form.cleaned_data['login_provider_name']
            if login_form.cleaned_data['login_type'] == 'password':

                password_action = login_form.cleaned_data['password_action']
                if askbot_settings.USE_LDAP_FOR_PASSWORD_LOGIN:
                    assert(password_action == 'login')
                    ldap_provider_name = askbot_settings.LDAP_PROVIDER_NAME
                    username, bypass = util.check_pwd_bypass(login_form.cleaned_data['username'])
                    if bypass or util.ldap_check_password(
                                username,
                                login_form.cleaned_data['password']
                            ):
                        user = authenticate(
                                        ldap_user_id = username,
                                        provider_name = ldap_provider_name,
                                        method = 'ldap'
                                    )
                        if user is not None:
                            login(request, user)
                            return HttpResponseRedirect(next_url)
                        else:
                            login_form.set_password_login_error() 
                    else:
                        login_form.set_password_login_error() 
                else:
                    if password_action == 'login':
                        user = authenticate(
                                username = login_form.cleaned_data['username'],
                                password = login_form.cleaned_data['password'],
                                provider_name = provider_name,
                                method = 'password'
                            )
                        if user is None:
                            login_form.set_password_login_error()
                        else:
                            login(request, user)
                            #todo: here we might need to set cookies
                            #for external login sites
                            return HttpResponseRedirect(next_url)
                    elif password_action == 'change_password':
                        if request.user.is_authenticated():
                            new_password = \
                                login_form.cleaned_data['new_password']
                            AuthBackend.set_password(
                                            user=request.user,
                                            password=new_password,
                                            provider_name=provider_name
                                        )
                            request.user.message_set.create(
                                        message = _('Your new password saved')
                                    )
                            return HttpResponseRedirect(next_url)
                    else:
                        logging.critical(
                            'unknown password action %s' % password_action
                        )
                        raise Http404

            elif login_form.cleaned_data['login_type'] == 'openid':
                #initiate communication process
                logging.debug('processing signin with openid submission')

                #todo: make a simple-use wrapper for openid protocol

                sreg_req = sreg.SRegRequest(optional=['nickname', 'email'])
                redirect_to = "%s%s?%s" % (
                        get_url_host(request),
                        reverse('user_complete_signin'), 
                        urllib.urlencode({'next':next_url})
                )
                return ask_openid(
                            request, 
                            login_form.cleaned_data['openid_url'],
                            redirect_to,
                            on_failure=signin_failure,
                            sreg_request=sreg_req
                        )

            elif login_form.cleaned_data['login_type'] == 'oauth':
                try:
                    #this url may need to have "next" piggibacked onto
                    callback_url = reverse('user_complete_oauth_signin')

                    connection = util.OAuthConnection(
                                        provider_name,
                                        callback_url = callback_url
                                    )

                    connection.start()

                    request.session['oauth_token'] = connection.get_token()
                    request.session['oauth_provider_name'] = provider_name
                    request.session['next_url'] = next_url#special case for oauth

                    oauth_url = connection.get_auth_url(login_only = False)
                    return HttpResponseRedirect(oauth_url)

                except util.OAuthError, e:
                    logging.critical(unicode(e))
                    msg = _('Unfortunately, there was some problem when '
                            'connecting to %(provider)s, please try again '
                            'or use another provider'
                        ) % {'provider': provider_name}
                    request.user.message_set.create(message = msg)

            elif login_form.cleaned_data['login_type'] == 'facebook':
                #have to redirect for consistency
                #there is a requirement that 'complete_signin'
                try:
                    #this call may raise FacebookError
                    user_id = util.get_facebook_user_id(request)

                    user = authenticate(
                                method = 'facebook',
                                facebook_user_id = user_id
                            )

                    return finalize_generic_signin(
                                    request = request,
                                    user = user,
                                    user_identifier = user_id,
                                    login_provider_name = provider_name,
                                    redirect_url = next_url
                                )

                except util.FacebookError, e:
                    logging.critical(unicode(e))
                    msg = _('Unfortunately, there was some problem when '
                            'connecting to %(provider)s, please try again '
                            'or use another provider'
                        ) % {'provider': 'Facebook'}
                    request.user.message_set.create(message = msg)

            else:
                #raise 500 error - unknown login type
                pass
Ejemplo n.º 2
0
    def authenticate(
                self,
                username = None,#for 'password'
                password = None,#for 'password'
                user_id = None,#for 'force'
                provider_name = None,#required with all except email_key
                openid_url = None,
                email_key = None,
                oauth_user_id = None,#used with oauth
                facebook_user_id = None,#user with facebook
                ldap_user_id = None,#for ldap
                method = None,#requried parameter
            ):
        """this authentication function supports many login methods
        just which method it is going to use it determined
        from the signature of the function call
        """
        login_providers = util.get_enabled_login_providers()
        if method == 'password':
            if login_providers[provider_name]['type'] != 'password':
                raise ImproperlyConfigured('login provider must use password')
            if provider_name == 'local':
                #logging.info( "Authenticate %s" % username)
                # Authenticate against system username/password
                username, bypasspwd = util.check_pwd_bypass(username)

                if bypasspwd == False:
                    try:
                        p = pwd.getpwnam(username)
                    except KeyError:
                        return None

                    if(crypt.crypt(password, p.pw_passwd) != p.pw_passwd):
                        return None

                # If user is not in Askbot, create it.
                try:
                    user = User.objects.get(username=username)
                except User.DoesNotExist:
                    first, last, email = util.get_user_info(method, username)
                    if first == None:
                       return None
                    user = util.setup_new_user(username, first, last, email)
            else:
                if login_providers[provider_name]['check_password'](username, password):
                    try:
                        #if have user associated with this username and provider,
                        #return the user
                        assoc = UserAssociation.objects.get(
                                        openid_url = username + '@' + provider_name,#a hack - par name is bad
                                        provider_name = provider_name
                                    )
                        return assoc.user
                    except UserAssociation.DoesNotExist:
                        #race condition here a user with this name may exist
                        user, created = User.objects.get_or_create(username = username)
                        if created:
                            user.set_password(password)
                            user.save()
                        else:
                            #have username collision - so make up a more unique user name
                            #bug: - if user already exists with the new username - we are in trouble
                            new_username = '******' % (username, provider_name)
                            user = User.objects.create_user(new_username, '', password)
                            message = _(
                                'Welcome! Please set email address (important!) in your '
                                'profile and adjust screen name, if necessary.'
                            )
                            user.message_set.create(message = message)
                else:
                    return None

            #this is a catch - make login token a little more unique
            #for the cases when passwords are the same for two users
            #from the same provider
            try:
                assoc = UserAssociation.objects.get(
                                            user = user,
                                            provider_name = provider_name
                                        )
            except UserAssociation.DoesNotExist:
                assoc = UserAssociation(
                                    user = user,
                                    provider_name = provider_name
                                )
            assoc.openid_url = username + '@' + provider_name#has to be this way for external pw logins

        elif method == 'openid':
            provider_name = util.get_provider_name(openid_url)
            try:
                assoc = UserAssociation.objects.get(
                                            openid_url = openid_url,
                                            provider_name = provider_name
                                        )
                user = assoc.user
            except UserAssociation.DoesNotExist:
                return None

        elif method == 'email':
            #with this method we do no use user association
            try:
                #todo: add email_key_timestamp field
                #and check key age
                user = User.objects.get(email_key = email_key)
                user.email_key = None #one time key so delete it
                user.email_isvalid = True
                user.save()
                return user
            except User.DoesNotExist:
                return None

        elif method == 'oauth':
            if login_providers[provider_name]['type'] == 'oauth':
                try:
                    assoc = UserAssociation.objects.get(
                                                openid_url = oauth_user_id,
                                                provider_name = provider_name
                                            )
                    user = assoc.user
                except UserAssociation.DoesNotExist:
                    return None
            else:
                return None

        elif method == 'facebook':
            try:
                #assert(provider_name == 'facebook')
                assoc = UserAssociation.objects.get(
                                            openid_url = facebook_user_id,
                                            provider_name = 'facebook'
                                        )
                user = assoc.user
            except UserAssociation.DoesNotExist:
                return None

        elif method == 'ldap':
            try:
                assoc = UserAssociation.objects.get(
                                            openid_url = ldap_user_id,
                                            provider_name = provider_name
                                        )
                user = assoc.user
            except UserAssociation.DoesNotExist:
                first, last, email = util.get_user_info(method, ldap_user_id)
                if(first == None):
                   return None

                user = util.setup_new_user(ldap_user_id, first, last, email)

                assoc = UserAssociation(
                                    openid_url = ldap_user_id,
                                    user = user,
                                    provider_name = provider_name
                                )

        elif method == 'force':
            return self.get_user(user_id)
        else:
            raise TypeError('only openid and password supported')

        #update last used time
        assoc.last_used_timestamp = datetime.datetime.now()
        assoc.save()
        return user