Exemple #1
0
def external_login_or_signup(request,
                             external_id,
                             external_domain,
                             credentials,
                             email,
                             fullname,
                             retfun=None):
    """Generic external auth login or signup"""

    # see if we have a map from this external_id to an edX username
    try:
        eamap = ExternalAuthMap.objects.get(external_id=external_id,
                                            external_domain=external_domain)
        log.debug('Found eamap=%s' % eamap)
    except ExternalAuthMap.DoesNotExist:
        # go render form for creating edX user
        eamap = ExternalAuthMap(external_id=external_id,
                                external_domain=external_domain,
                                external_credentials=json.dumps(credentials))
        eamap.external_email = email
        eamap.external_name = fullname
        eamap.internal_password = generate_password()
        log.debug('Created eamap=%s' % eamap)

        eamap.save()

    internal_user = eamap.user
    if internal_user is None:
        log.debug('No user for %s yet, doing signup' % eamap.external_email)
        return signup(request, eamap)

    uname = internal_user.username
    user = authenticate(username=uname, password=eamap.internal_password)
    if user is None:
        log.warning("External Auth Login failed for %s / %s" %
                    (uname, eamap.internal_password))
        return signup(request, eamap)

    if not user.is_active:
        log.warning("User %s is not active" % (uname))
        # TODO: improve error page
        msg = 'Account not yet activated: please look for link in your email'
        return default_render_failure(request, msg)

    login(request, user)
    request.session.set_expiry(0)
    student_views.try_change_enrollment(request)
    log.info("Login success - {0} ({1})".format(user.username, user.email))
    if retfun is None:
        return redirect('/')
    return retfun()
Exemple #2
0
def external_login_or_signup(request,
                             external_id,
                             external_domain,
                             credentials,
                             email,
                             fullname,
                             retfun=None):
    """Generic external auth login or signup"""

    # see if we have a map from this external_id to an edX username
    try:
        eamap = ExternalAuthMap.objects.get(external_id=external_id,
                                            external_domain=external_domain)
        log.debug('Found eamap=%s' % eamap)
    except ExternalAuthMap.DoesNotExist:
        # go render form for creating edX user
        eamap = ExternalAuthMap(external_id=external_id,
                                external_domain=external_domain,
                                external_credentials=json.dumps(credentials))
        eamap.external_email = email
        eamap.external_name = fullname
        eamap.internal_password = generate_password()
        log.debug('Created eamap=%s' % eamap)

        eamap.save()

    internal_user = eamap.user
    if internal_user is None:
        log.debug('No user for %s yet, doing signup' % eamap.external_email)
        return signup(request, eamap)

    uname = internal_user.username
    user = authenticate(username=uname, password=eamap.internal_password)
    if user is None:
        log.warning("External Auth Login failed for %s / %s" %
                    (uname, eamap.internal_password))
        return signup(request, eamap)

    if not user.is_active:
        log.warning("User %s is not active" % (uname))
        # TODO: improve error page
        msg = 'Account not yet activated: please look for link in your email'
        return default_render_failure(request, msg)

    login(request, user)
    request.session.set_expiry(0)
    student_views.try_change_enrollment(request)
    log.info("Login success - {0} ({1})".format(user.username, user.email))
    if retfun is None:
        return redirect('/')
    return retfun()
Exemple #3
0
def authentication_success(request):
    '''
    新用户注册时
    用户直接走oauth后通过python-social-auth的auth后,成功会回调到此处,
    此时django的用户应该是未登录状态 request.user.is_authenticated() is False
    '''
    detail = request.session.get('authentication_user_detail')
    inviter_id = request.session.get('inviter_id')
    provider = detail['social_provider']
    strategy = get_strategy(provider)
    enrollment_action = request.session.get('enrollment_action')
    course_id = request.session.get('course_id')
    user, _created = _get_or_create_oauth_user(strategy, detail, request)
    # 如果有邀请
    if inviter_id:
        _create_user_invite(inviter_id, user)
    login(request, user)
    user_profile = user.profile
    user_profile.last_login_ip = request.META.get('REMOTE_ADDR', None)
    user_profile.save()
    # 如果用户没有登录就选课,并且这时候选择的是oauth,尝试enroll课程
    if enrollment_action:
        request.method = 'POST'
        request.POST = request.POST.copy()
        request.POST['enrollment_action'] = enrollment_action
        request.POST['course_id'] = course_id
        try_change_enrollment(request)
    next_url = request.session.get('next', '')
    context = {'next': next_url}

    track_log(request, 'oauth.user.login_success', {
        'success': True,
        'uid': user.id,
        'provider': strategy.backend.name,
    })
    return render_to_response('xuetangx/oauth/oauth_login_success.html',
                              context)
def authentication_success(request):
    '''
    新用户注册时
    用户直接走oauth后通过python-social-auth的auth后,成功会回调到此处,
    此时django的用户应该是未登录状态 request.user.is_authenticated() is False
    '''
    detail = request.session.get('authentication_user_detail')
    inviter_id = request.session.get('inviter_id')
    provider = detail['social_provider']
    strategy = get_strategy(provider)
    enrollment_action = request.session.get('enrollment_action')
    course_id = request.session.get('course_id')
    user, _created = _get_or_create_oauth_user(strategy, detail, request)
    # 如果有邀请
    if inviter_id:
        _create_user_invite(inviter_id, user)
    login(request, user)
    user_profile = user.profile
    user_profile.last_login_ip = request.META.get('REMOTE_ADDR', None)
    user_profile.save()
    # 如果用户没有登录就选课,并且这时候选择的是oauth,尝试enroll课程
    if enrollment_action:
        request.method = 'POST'
        request.POST = request.POST.copy()
        request.POST['enrollment_action'] = enrollment_action
        request.POST['course_id'] = course_id
        try_change_enrollment(request)
    next_url = request.session.get('next', '')
    context = {'next': next_url}    

    track_log(request, 'oauth.user.login_success', {
        'success': True,
        'uid': user.id,
        'provider': strategy.backend.name,
    })
    return render_to_response('xuetangx/oauth/oauth_login_success.html', context)
Exemple #5
0
        eamap.save()
        AUDIT_LOG.info("User registered with external_auth %s",
                       post_vars['username'])
        AUDIT_LOG.info('Updated ExternalAuthMap for %s to be %s',
                       post_vars['username'], eamap)

        if settings.FEATURES.get('BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'):
            log.info('bypassing activation email')
            login_user.is_active = True
            login_user.save()
            AUDIT_LOG.info(
                u"Login activated on extauth account - {0} ({1})".format(
                    login_user.username, login_user.email))

    dog_stats_api.increment("common.student.account_created")
    redirect_url = try_change_enrollment(request)

    # Resume the third-party-auth pipeline if necessary.
    if settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH') and pipeline.running(
            request):
        running_pipeline = pipeline.get(request)
        redirect_url = pipeline.get_complete_url(running_pipeline['backend'])

    response = JsonResponse({
        'success': True,
        'redirect_url': redirect_url,
    })

    # set the login cookie for the edx marketing site
    # we want this cookie to be accessed via javascript
    # so httponly is set to None
Exemple #6
0
def _external_login_or_signup(request,
                              external_id,
                              external_domain,
                              credentials,
                              email,
                              fullname,
                              retfun=None):
    """Generic external auth login or signup"""

    # see if we have a map from this external_id to an edX username
    try:
        eamap = ExternalAuthMap.objects.get(external_id=external_id,
                                            external_domain=external_domain)
        log.debug('Found eamap=%s', eamap)
    except ExternalAuthMap.DoesNotExist:
        # go render form for creating edX user
        eamap = ExternalAuthMap(external_id=external_id,
                                external_domain=external_domain,
                                external_credentials=json.dumps(credentials))
        eamap.external_email = email
        eamap.external_name = fullname
        eamap.internal_password = generate_password()
        log.debug('Created eamap=%s', eamap)
        eamap.save()

    log.info(u"External_Auth login_or_signup for %s : %s : %s : %s",
             external_domain, external_id, email, fullname)
    uses_shibboleth = settings.MITX_FEATURES.get(
        'AUTH_USE_SHIB') and external_domain.startswith(
            SHIBBOLETH_DOMAIN_PREFIX)
    internal_user = eamap.user
    if internal_user is None:
        if uses_shibboleth:
            # if we are using shib, try to link accounts using email
            try:
                link_user = User.objects.get(email=eamap.external_email)
                if not ExternalAuthMap.objects.filter(user=link_user).exists():
                    # if there's no pre-existing linked eamap, we link the user
                    eamap.user = link_user
                    eamap.save()
                    internal_user = link_user
                    log.info('SHIB: Linking existing account for %s',
                             eamap.external_email)
                    # now pass through to log in
                else:
                    # otherwise, there must have been an error, b/c we've already linked a user with these external
                    # creds
                    failure_msg = _(
                        dedent("""
                        You have already created an account using an external login like WebAuth or Shibboleth.
                        Please contact %s for support """ %
                               getattr(settings, 'TECH_SUPPORT_EMAIL',
                                       '*****@*****.**')))
                    return default_render_failure(request, failure_msg)
            except User.DoesNotExist:
                log.info('SHIB: No user for %s yet, doing signup',
                         eamap.external_email)
                return _signup(request, eamap)
        else:
            log.info('No user for %s yet. doing signup', eamap.external_email)
            return _signup(request, eamap)

    # We trust shib's authentication, so no need to authenticate using the password again
    uname = internal_user.username
    if uses_shibboleth:
        user = internal_user
        # Assuming this 'AUTHENTICATION_BACKENDS' is set in settings, which I think is safe
        if settings.AUTHENTICATION_BACKENDS:
            auth_backend = settings.AUTHENTICATION_BACKENDS[0]
        else:
            auth_backend = 'django.contrib.auth.backends.ModelBackend'
        user.backend = auth_backend
        AUDIT_LOG.info('Linked user "%s" logged in via Shibboleth', user.email)
    else:
        user = authenticate(username=uname,
                            password=eamap.internal_password,
                            request=request)
    if user is None:
        # we want to log the failure, but don't want to log the password attempted:
        AUDIT_LOG.warning('External Auth Login failed for "%s"', uname)
        return _signup(request, eamap)

    if not user.is_active:
        AUDIT_LOG.warning('User "%s" is not active after external login',
                          uname)
        # TODO: improve error page
        msg = 'Account not yet activated: please look for link in your email'
        return default_render_failure(request, msg)

    login(request, user)
    request.session.set_expiry(0)

    # Now to try enrollment
    # Need to special case Shibboleth here because it logs in via a GET.
    # testing request.method for extra paranoia
    if uses_shibboleth and request.method == 'GET':
        enroll_request = _make_shib_enrollment_request(request)
        student_views.try_change_enrollment(enroll_request)
    else:
        student_views.try_change_enrollment(request)
    AUDIT_LOG.info("Login success - %s (%s)", user.username, user.email)
    if retfun is None:
        return redirect('/')
    return retfun()
Exemple #7
0
def _external_login_or_signup(request,
                              external_id,
                              external_domain,
                              credentials,
                              email,
                              fullname,
                              retfun=None):
    """Generic external auth login or signup"""

    # see if we have a map from this external_id to an edX username
    try:
        eamap = ExternalAuthMap.objects.get(external_id=external_id,
                                            external_domain=external_domain)
        log.debug('Found eamap=%s', eamap)
    except ExternalAuthMap.DoesNotExist:
        # go render form for creating edX user
        eamap = ExternalAuthMap(external_id=external_id,
                                external_domain=external_domain,
                                external_credentials=json.dumps(credentials))
        eamap.external_email = email
        eamap.external_name = fullname
        eamap.internal_password = generate_password()
        log.debug('Created eamap=%s', eamap)
        eamap.save()

    log.info(u"External_Auth login_or_signup for %s : %s : %s : %s", external_domain, external_id, email, fullname)
    uses_shibboleth = settings.MITX_FEATURES.get('AUTH_USE_SHIB') and external_domain.startswith(SHIBBOLETH_DOMAIN_PREFIX)
    internal_user = eamap.user
    if internal_user is None:
        if uses_shibboleth:
            # if we are using shib, try to link accounts using email
            try:
                link_user = User.objects.get(email=eamap.external_email)
                if not ExternalAuthMap.objects.filter(user=link_user).exists():
                    # if there's no pre-existing linked eamap, we link the user
                    eamap.user = link_user
                    eamap.save()
                    internal_user = link_user
                    log.info('SHIB: Linking existing account for %s', eamap.external_email)
                    # now pass through to log in
                else:
                    # otherwise, there must have been an error, b/c we've already linked a user with these external
                    # creds
                    failure_msg = _(dedent("""
                        You have already created an account using an external login like WebAuth or Shibboleth.
                        Please contact %s for support """
                                           % getattr(settings, 'TECH_SUPPORT_EMAIL', '*****@*****.**')))
                    return default_render_failure(request, failure_msg)
            except User.DoesNotExist:
                log.info('SHIB: No user for %s yet, doing signup', eamap.external_email)
                return _signup(request, eamap)
        else:
            log.info('No user for %s yet. doing signup', eamap.external_email)
            return _signup(request, eamap)

    # We trust shib's authentication, so no need to authenticate using the password again
    uname = internal_user.username
    if uses_shibboleth:
        user = internal_user
        # Assuming this 'AUTHENTICATION_BACKENDS' is set in settings, which I think is safe
        if settings.AUTHENTICATION_BACKENDS:
            auth_backend = settings.AUTHENTICATION_BACKENDS[0]
        else:
            auth_backend = 'django.contrib.auth.backends.ModelBackend'
        user.backend = auth_backend
        AUDIT_LOG.info('Linked user "%s" logged in via Shibboleth', user.email)
    else:
        user = authenticate(username=uname, password=eamap.internal_password, request=request)
    if user is None:
        # we want to log the failure, but don't want to log the password attempted:
        AUDIT_LOG.warning('External Auth Login failed for "%s"', uname)
        return _signup(request, eamap)

    if not user.is_active:
        AUDIT_LOG.warning('User "%s" is not active after external login', uname)
        # TODO: improve error page
        msg = 'Account not yet activated: please look for link in your email'
        return default_render_failure(request, msg)

    login(request, user)
    request.session.set_expiry(0)

    # Now to try enrollment
    # Need to special case Shibboleth here because it logs in via a GET.
    # testing request.method for extra paranoia
    if uses_shibboleth and request.method == 'GET':
        enroll_request = _make_shib_enrollment_request(request)
        student_views.try_change_enrollment(enroll_request)
    else:
        student_views.try_change_enrollment(request)
    AUDIT_LOG.info("Login success - %s (%s)", user.username, user.email)
    if retfun is None:
        return redirect('/')
    return retfun()