Пример #1
0
def login_user(request):
    """
    AJAX request to log in the user.
    """
    third_party_auth_requested = third_party_auth.is_enabled() and pipeline.running(request)
    first_party_auth_requested = bool(request.POST.get('email')) or bool(request.POST.get('password'))
    is_user_third_party_authenticated = False

    try:
        if third_party_auth_requested and not first_party_auth_requested:
            # The user has already authenticated via third-party auth and has not
            # asked to do first party auth by supplying a username or password. We
            # now want to put them through the same logging and cookie calculation
            # logic as with first-party auth.

            # This nested try is due to us only returning an HttpResponse in this
            # one case vs. JsonResponse everywhere else.
            try:
                user = _do_third_party_auth(request)
                is_user_third_party_authenticated = True
            except AuthFailedError as e:
                return HttpResponse(e.value, content_type="text/plain", status=403)
        else:
            user = _get_user_by_email(request)

        _check_shib_redirect(user)
        _check_excessive_login_attempts(user)

        possibly_authenticated_user = user

        if not is_user_third_party_authenticated:
            possibly_authenticated_user = _authenticate_first_party(request, user)
            if possibly_authenticated_user and password_policy_compliance.should_enforce_compliance_on_login():
                # Important: This call must be made AFTER the user was successfully authenticated.
                _enforce_password_policy_compliance(request, possibly_authenticated_user)

        if possibly_authenticated_user is None or not possibly_authenticated_user.is_active:
            _handle_failed_authentication(user, possibly_authenticated_user)

        if not is_edly_user_allowed_to_login(request, possibly_authenticated_user):
            raise AuthFailedError(_('You are not allowed to login on this site.'))

        _handle_successful_authentication_and_login(possibly_authenticated_user, request)

        redirect_url = None  # The AJAX method calling should know the default destination upon success
        if is_user_third_party_authenticated:
            running_pipeline = pipeline.get(request)
            redirect_url = pipeline.get_complete_url(backend_name=running_pipeline['backend'])

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

        # Ensure that the external marketing site can
        # detect that the user is logged in.
        return set_logged_in_cookies(request, response, possibly_authenticated_user)
    except AuthFailedError as error:
        log.exception(error.get_response())
        return JsonResponse(error.get_response())
Пример #2
0
def login_user(request):
    """
    AJAX request to log in the user.
    """
    third_party_auth_requested = third_party_auth.is_enabled() and pipeline.running(request)
    trumped_by_first_party_auth = bool(request.POST.get('email')) or bool(request.POST.get('password'))
    was_authenticated_third_party = False

    try:
        if third_party_auth_requested and not trumped_by_first_party_auth:
            # The user has already authenticated via third-party auth and has not
            # asked to do first party auth by supplying a username or password. We
            # now want to put them through the same logging and cookie calculation
            # logic as with first-party auth.

            # This nested try is due to us only returning an HttpResponse in this
            # one case vs. JsonResponse everywhere else.
            try:
                email_user = _do_third_party_auth(request)
                was_authenticated_third_party = True
            except AuthFailedError as e:
                return HttpResponse(e.value, content_type="text/plain", status=403)
        else:
            email_user = _get_user_by_email(request)

        _check_shib_redirect(email_user)
        _check_excessive_login_attempts(email_user)
        _check_forced_password_reset(email_user)

        possibly_authenticated_user = email_user

        if not was_authenticated_third_party:
            possibly_authenticated_user = _authenticate_first_party(request, email_user)
            if possibly_authenticated_user and password_policy_compliance.should_enforce_compliance_on_login():
                # Important: This call must be made AFTER the user was successfully authenticated.
                _enforce_password_policy_compliance(request, possibly_authenticated_user)

        if possibly_authenticated_user is None or not possibly_authenticated_user.is_active:
            _handle_failed_authentication(email_user)

        _handle_successful_authentication_and_login(possibly_authenticated_user, request)

        redirect_url = None  # The AJAX method calling should know the default destination upon success
        if was_authenticated_third_party:
            running_pipeline = pipeline.get(request)
            redirect_url = pipeline.get_complete_url(backend_name=running_pipeline['backend'])

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

        # Ensure that the external marketing site can
        # detect that the user is logged in.
        return set_logged_in_cookies(request, response, possibly_authenticated_user)
    except AuthFailedError as error:
        log.exception(error.get_response())
        return JsonResponse(error.get_response())
Пример #3
0
    def clean(self):
        """
        Overrides the clean method to allow for the enforcement of password policy requirements.
        """
        cleaned_data = super(PasswordPolicyAwareAdminAuthForm, self).clean()

        if password_policy_compliance.should_enforce_compliance_on_login():
            try:
                password_policy_compliance.enforce_compliance_on_login(self.user_cache, cleaned_data['password'])
            except password_policy_compliance.NonCompliantPasswordWarning as e:
                # Allow login, but warn the user that they will be required to reset their password soon.
                messages.warning(self.request, e.message)
            except password_policy_compliance.NonCompliantPasswordException as e:
                # Prevent the login attempt.
                raise ValidationError(e.message)

        return cleaned_data
Пример #4
0
    def clean(self):
        """
        Overrides the clean method to allow for the enforcement of password policy requirements.
        """
        cleaned_data = super().clean()

        if password_policy_compliance.should_enforce_compliance_on_login():
            try:
                password_policy_compliance.enforce_compliance_on_login(self.user_cache, cleaned_data['password'])
            except password_policy_compliance.NonCompliantPasswordWarning as e:
                # Allow login, but warn the user that they will be required to reset their password soon.
                messages.warning(self.request, HTML(str(e)))
            except password_policy_compliance.NonCompliantPasswordException as e:
                # Prevent the login attempt.
                raise ValidationError(HTML(str(e)))  # lint-amnesty, pylint: disable=raise-missing-from

        return cleaned_data
Пример #5
0
    def clean(self):
        """
        Overrides the clean method to allow for the enforcement of password policy requirements.
        """
        cleaned_data = super(PasswordPolicyAwareAdminAuthForm, self).clean()

        if password_policy_compliance.should_enforce_compliance_on_login():
            try:
                password_policy_compliance.enforce_compliance_on_login(
                    self.user_cache, cleaned_data['password'])
            except password_policy_compliance.NonCompliantPasswordWarning as e:
                # Allow login, but warn the user that they will be required to reset their password soon.
                messages.warning(self.request, e.message)
            except password_policy_compliance.NonCompliantPasswordException as e:
                # Prevent the login attempt.
                raise ValidationError(e.message)

        return cleaned_data
Пример #6
0
 def test_should_enforce_compliance_on_login(self):
     """
     Test that if the config is disabled or nonexistent nothing is returned
     """
     # Parameters don't matter for this method as it only tests the config
     self.assertTrue(should_enforce_compliance_on_login())
Пример #7
0
def login_user(request):
    """
    AJAX request to log in the user.

    Arguments:
        request (HttpRequest)

    Required params:
        email, password

    Optional params:
        analytics: a JSON-encoded object with additional info to include in the login analytics event. The only
            supported field is "enroll_course_id" to indicate that the user logged in while enrolling in a particular
            course.

    Returns:
        HttpResponse: 200 if successful.
            Ex. {'success': true}
        HttpResponse: 400 if the request failed.
            Ex. {'success': false, 'value': '{'success': false, 'value: 'Email or password is incorrect.'}
        HttpResponse: 403 if successful authentication with a third party provider but does not have a linked account.
            Ex. {'success': false, 'error_code': 'third-party-auth-with-no-linked-account'}

    Example Usage:

        POST /login_ajax
        with POST params `email`, `password`

        200 {'success': true}

    """
    _parse_analytics_param_for_course_id(request)

    third_party_auth_requested = third_party_auth.is_enabled(
    ) and pipeline.running(request)
    first_party_auth_requested = bool(request.POST.get('email')) or bool(
        request.POST.get('password'))
    is_user_third_party_authenticated = False

    set_custom_metric('login_user_course_id', request.POST.get('course_id'))

    try:
        if third_party_auth_requested and not first_party_auth_requested:
            # The user has already authenticated via third-party auth and has not
            # asked to do first party auth by supplying a username or password. We
            # now want to put them through the same logging and cookie calculation
            # logic as with first-party auth.

            # This nested try is due to us only returning an HttpResponse in this
            # one case vs. JsonResponse everywhere else.
            try:
                user = _do_third_party_auth(request)
                is_user_third_party_authenticated = True
                set_custom_metric('login_user_tpa_success', True)
            except AuthFailedError as e:
                set_custom_metric('login_user_tpa_success', False)
                set_custom_metric('login_user_tpa_failure_msg', e.value)

                # user successfully authenticated with a third party provider, but has no linked Open edX account
                response_content = e.get_response()
                response_content[
                    'error_code'] = 'third-party-auth-with-no-linked-account'
                return JsonResponse(response_content, status=403)
        else:
            user = _get_user_by_email(request)

        _check_excessive_login_attempts(user)

        possibly_authenticated_user = user

        if not is_user_third_party_authenticated:
            possibly_authenticated_user = _authenticate_first_party(
                request, user, third_party_auth_requested)
            if possibly_authenticated_user and password_policy_compliance.should_enforce_compliance_on_login(
            ):
                # Important: This call must be made AFTER the user was successfully authenticated.
                _enforce_password_policy_compliance(
                    request, possibly_authenticated_user)

        if possibly_authenticated_user is None or not possibly_authenticated_user.is_active:
            _handle_failed_authentication(user, possibly_authenticated_user)

        _handle_successful_authentication_and_login(
            possibly_authenticated_user, request)

        redirect_url = None  # The AJAX method calling should know the default destination upon success
        if is_user_third_party_authenticated:
            running_pipeline = pipeline.get(request)
            redirect_url = pipeline.get_complete_url(
                backend_name=running_pipeline['backend'])

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

        # Ensure that the external marketing site can
        # detect that the user is logged in.
        response = set_logged_in_cookies(request, response,
                                         possibly_authenticated_user)
        set_custom_metric('login_user_auth_failed_error', False)
        set_custom_metric('login_user_response_status', response.status_code)
        set_custom_metric('login_user_redirect_url', redirect_url)
        return response
    except AuthFailedError as error:
        log.exception(error.get_response())
        response = JsonResponse(error.get_response(), status=400)
        set_custom_metric('login_user_auth_failed_error', True)
        set_custom_metric('login_user_response_status', response.status_code)
        return response
Пример #8
0
from openedx.core.djangoapps.user_authn.views.login import redirect_to_lms_login
from openedx.core.djangoapps.verified_track_content import views as verified_track_content_views
from openedx.features.enterprise_support.api import enterprise_enabled
from common.djangoapps.student import views as student_views
from common.djangoapps.util import views as util_views

RESET_COURSE_DEADLINES_NAME = 'reset_course_deadlines'
RENDER_XBLOCK_NAME = 'render_xblock'
COURSE_DATES_NAME = 'dates'

if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
    django_autodiscover()
    admin.site.site_header = _('LMS Administration')
    admin.site.site_title = admin.site.site_header

    if password_policy_compliance.should_enforce_compliance_on_login():
        admin.site.login_form = PasswordPolicyAwareAdminAuthForm

# Custom error pages
# These are used by Django to render these error codes. Do not remove.
# pylint: disable=invalid-name
handler404 = static_template_view_views.render_404
handler500 = static_template_view_views.render_500

notification_prefs_urls = [
    url(r'^notification_prefs/enable/', notification_prefs_views.ajax_enable),
    url(r'^notification_prefs/disable/',
        notification_prefs_views.ajax_disable),
    url(r'^notification_prefs/status/', notification_prefs_views.ajax_status),
    url(
        r'^notification_prefs/unsubscribe/(?P<token>[a-zA-Z0-9-_=]+)/',
Пример #9
0
def login_user(request, api_version='v1'):
    """
    AJAX request to log in the user.

    Arguments:
        request (HttpRequest)

    Required params:
        email, password

    Optional params:
        analytics: a JSON-encoded object with additional info to include in the login analytics event. The only
            supported field is "enroll_course_id" to indicate that the user logged in while enrolling in a particular
            course.

    Returns:
        HttpResponse: 200 if successful.
            Ex. {'success': true}
        HttpResponse: 400 if the request failed.
            Ex. {'success': false, 'value': '{'success': false, 'value: 'Email or password is incorrect.'}
        HttpResponse: 403 if successful authentication with a third party provider but does not have a linked account.
            Ex. {'success': false, 'error_code': 'third-party-auth-with-no-linked-account'}

    Example Usage:

        POST /login_ajax
        with POST params `email`, `password`

        200 {'success': true}

    """
    _parse_analytics_param_for_course_id(request)

    third_party_auth_requested = third_party_auth.is_enabled(
    ) and pipeline.running(request)
    first_party_auth_requested = bool(request.POST.get('email')) or bool(
        request.POST.get('password'))
    is_user_third_party_authenticated = False

    set_custom_attribute('login_user_course_id', request.POST.get('course_id'))

    if is_require_third_party_auth_enabled(
    ) and not third_party_auth_requested:
        return HttpResponseForbidden(
            "Third party authentication is required to login. Username and password were received instead."
        )
    possibly_authenticated_user = None
    try:
        if third_party_auth_requested and not first_party_auth_requested:
            # The user has already authenticated via third-party auth and has not
            # asked to do first party auth by supplying a username or password. We
            # now want to put them through the same logging and cookie calculation
            # logic as with first-party auth.

            # This nested try is due to us only returning an HttpResponse in this
            # one case vs. JsonResponse everywhere else.
            try:
                user = _do_third_party_auth(request)
                is_user_third_party_authenticated = True
                set_custom_attribute('login_user_tpa_success', True)
            except AuthFailedError as e:
                set_custom_attribute('login_user_tpa_success', False)
                set_custom_attribute('login_user_tpa_failure_msg', e.value)
                if e.error_code:
                    set_custom_attribute('login_error_code', e.error_code)

                # user successfully authenticated with a third party provider, but has no linked Open edX account
                response_content = e.get_response()
                return JsonResponse(response_content, status=403)
        else:
            user = _get_user_by_email_or_username(request, api_version)

        _check_excessive_login_attempts(user)

        possibly_authenticated_user = user

        if not is_user_third_party_authenticated:
            possibly_authenticated_user = _authenticate_first_party(
                request, user, third_party_auth_requested)
            if possibly_authenticated_user and password_policy_compliance.should_enforce_compliance_on_login(
            ):
                # Important: This call must be made AFTER the user was successfully authenticated.
                _enforce_password_policy_compliance(
                    request, possibly_authenticated_user)
                check_pwned_password_and_send_track_event.delay(
                    user.id, request.POST.get('password'), user.is_staff)

        if possibly_authenticated_user is None or not (
                possibly_authenticated_user.is_active
                or settings.MARKETING_EMAILS_OPT_IN):
            _handle_failed_authentication(user, possibly_authenticated_user)

        _handle_successful_authentication_and_login(
            possibly_authenticated_user, request)

        # The AJAX method calling should know the default destination upon success
        redirect_url, finish_auth_url = None, ''

        if third_party_auth_requested:
            running_pipeline = pipeline.get(request)
            finish_auth_url = pipeline.get_complete_url(
                backend_name=running_pipeline['backend'])

        if is_user_third_party_authenticated:
            redirect_url = finish_auth_url
        elif should_redirect_to_authn_microfrontend():
            next_url, root_url = get_next_url_for_login_page(request,
                                                             include_host=True)
            redirect_url = get_redirect_url_with_host(
                root_url,
                enterprise_selection_page(request, possibly_authenticated_user,
                                          finish_auth_url or next_url))

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

        # Ensure that the external marketing site can
        # detect that the user is logged in.
        response = set_logged_in_cookies(request, response,
                                         possibly_authenticated_user)
        set_custom_attribute('login_user_auth_failed_error', False)
        set_custom_attribute('login_user_response_status',
                             response.status_code)
        set_custom_attribute('login_user_redirect_url', redirect_url)
        mark_user_change_as_expected(response, user.id)
        return response
    except AuthFailedError as error:
        response_content = error.get_response()
        log.exception(response_content)

        error_code = response_content.get('error_code')
        if error_code:
            set_custom_attribute('login_error_code', error_code)
        email_or_username_key = 'email' if api_version == API_V1 else 'email_or_username'
        email_or_username = request.POST.get(email_or_username_key, None)
        email_or_username = possibly_authenticated_user.email \
            if possibly_authenticated_user else email_or_username
        response_content['email'] = email_or_username
        response = JsonResponse(response_content, status=400)
        set_custom_attribute('login_user_auth_failed_error', True)
        set_custom_attribute('login_user_response_status',
                             response.status_code)
        return response
Пример #10
0
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.verified_track_content import views as verified_track_content_views
from openedx.features.enterprise_support.api import enterprise_enabled
from ratelimitbackend import admin
from static_template_view import views as static_template_view_views
from staticbook import views as staticbook_views
from student import views as student_views
from track import views as track_views
from util import views as util_views

if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
    django_autodiscover()
    admin.site.site_header = _('LMS Administration')
    admin.site.site_title = admin.site.site_header

    if password_policy_compliance.should_enforce_compliance_on_login():
        admin.site.login_form = PasswordPolicyAwareAdminAuthForm

# Custom error pages
# These are used by Django to render these error codes. Do not remove.
# pylint: disable=invalid-name
handler404 = static_template_view_views.render_404
handler500 = static_template_view_views.render_500

urlpatterns = [
    url(r'^$', branding_views.index, name='root'),   # Main marketing page, or redirect to courseware

    url(r'', include('student.urls')),
    # TODO: Move lms specific student views out of common code
    url(r'^dashboard/?$', student_views.student_dashboard, name='dashboard'),
    url(r'^change_enrollment$', student_views.change_enrollment, name='change_enrollment'),
Пример #11
0
def login_user(request):
    """
    AJAX request to log in the user.
    """
    _parse_analytics_param_for_course_id(request)

    third_party_auth_requested = third_party_auth.is_enabled(
    ) and pipeline.running(request)
    first_party_auth_requested = bool(request.POST.get('email')) or bool(
        request.POST.get('password'))
    is_user_third_party_authenticated = False

    set_custom_metric('login_user_enrollment_action',
                      request.POST.get('enrollment_action'))
    set_custom_metric('login_user_course_id', request.POST.get('course_id'))

    try:
        if third_party_auth_requested and not first_party_auth_requested:
            # The user has already authenticated via third-party auth and has not
            # asked to do first party auth by supplying a username or password. We
            # now want to put them through the same logging and cookie calculation
            # logic as with first-party auth.

            # This nested try is due to us only returning an HttpResponse in this
            # one case vs. JsonResponse everywhere else.
            try:
                user = _do_third_party_auth(request)
                is_user_third_party_authenticated = True
                set_custom_metric('login_user_tpa_success', True)
            except AuthFailedError as e:
                set_custom_metric('login_user_tpa_success', False)
                set_custom_metric('login_user_tpa_failure_msg', e.value)

                # user successfully authenticated with a third party provider, but has no linked Open edX account
                response_content = e.get_response()
                response_content[
                    'error_code'] = 'third-party-auth-with-no-linked-account'
                return JsonResponse(response_content, status=403)
        else:
            user = _get_user_by_email(request)

        _check_excessive_login_attempts(user)

        possibly_authenticated_user = user

        if not is_user_third_party_authenticated:
            possibly_authenticated_user = _authenticate_first_party(
                request, user)
            if possibly_authenticated_user and password_policy_compliance.should_enforce_compliance_on_login(
            ):
                # Important: This call must be made AFTER the user was successfully authenticated.
                _enforce_password_policy_compliance(
                    request, possibly_authenticated_user)

        if possibly_authenticated_user is None or not possibly_authenticated_user.is_active:
            _handle_failed_authentication(user, possibly_authenticated_user)

        _handle_successful_authentication_and_login(
            possibly_authenticated_user, request)

        redirect_url = None  # The AJAX method calling should know the default destination upon success
        if is_user_third_party_authenticated:
            running_pipeline = pipeline.get(request)
            redirect_url = pipeline.get_complete_url(
                backend_name=running_pipeline['backend'])

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

        # Ensure that the external marketing site can
        # detect that the user is logged in.
        response = set_logged_in_cookies(request, response,
                                         possibly_authenticated_user)
        set_custom_metric('login_user_auth_failed_error', False)
        set_custom_metric('login_user_response_status', response.status_code)
        return response
    except AuthFailedError as error:
        log.exception(error.get_response())
        # original code returned a 200 status code with status=False for errors. This flag
        # is used for rolling out a transition to using a 400 status code for errors, which
        # is a breaking-change, but will hopefully be a tolerable breaking-change.
        status = 400 if UPDATE_LOGIN_USER_ERROR_STATUS_CODE.is_enabled(
        ) else 200
        response = JsonResponse(error.get_response(), status=status)
        set_custom_metric('login_user_auth_failed_error', True)
        set_custom_metric('login_user_response_status', response.status_code)
        return response
Пример #12
0
 def test_should_enforce_compliance_on_login(self):
     """
     Test that if the config is disabled or nonexistent nothing is returned
     """
     # Parameters don't matter for this method as it only tests the config
     self.assertTrue(should_enforce_compliance_on_login())
Пример #13
0
def login_user(request):
    """
    AJAX request to log in the user.
    """
    post_data = request.POST.copy()

    # Decrypt form data if it is encrypted
    if 'data_token' in request.POST:
        data_token = request.POST.get('data_token')

        try:
            decoded_data = jwt.decode(
                data_token,
                settings.EDRAAK_LOGISTRATION_SECRET_KEY,
                verify=False,
                algorithms=[settings.EDRAAK_LOGISTRATION_SIGNING_ALGORITHM])
            post_data.update(decoded_data)

        except jwt.ExpiredSignatureError:
            err_msg = u"The provided data_token has been expired"
            AUDIT_LOG.warning(err_msg)

            return JsonResponse({
                "success": False,
                "value": err_msg,
            },
                                status=400)

        except jwt.DecodeError:
            err_msg = u"Signature verification failed"
            AUDIT_LOG.warning(err_msg)

            return JsonResponse({
                "success": False,
                "value": err_msg,
            },
                                status=400)

        except (jwt.InvalidTokenError, ValueError):
            err_msg = u"Invalid token"
            AUDIT_LOG.warning(err_msg)

            return JsonResponse({
                "success": False,
                "value": err_msg,
            },
                                status=400)

    third_party_auth_requested = third_party_auth.is_enabled(
    ) and pipeline.running(request)
    trumped_by_first_party_auth = bool(post_data.get('email')) or bool(
        post_data.get('password'))
    was_authenticated_third_party = False
    parent_user = None
    child_user = None

    try:
        if third_party_auth_requested and not trumped_by_first_party_auth:
            # The user has already authenticated via third-party auth and has not
            # asked to do first party auth by supplying a username or password. We
            # now want to put them through the same logging and cookie calculation
            # logic as with first-party auth.

            # This nested try is due to us only returning an HttpResponse in this
            # one case vs. JsonResponse everywhere else.
            try:
                email_user = _do_third_party_auth(request)
                was_authenticated_third_party = True
            except AuthFailedError as e:
                return HttpResponse(e.value,
                                    content_type="text/plain",
                                    status=403)

        elif 'child_user_id' in post_data:
            child_user_id = post_data['child_user_id']
            try:
                child_user = User.objects.get(id=child_user_id)
            except User.DoesNotExist:
                if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
                    AUDIT_LOG.warning(
                        u"Child login failed - Unknown child user id")
                else:
                    AUDIT_LOG.warning(
                        u"Child login failed - Unknown child user id: {0}".
                        format(child_user_id))

        else:
            email_user = _get_user_by_email(request, post_data=post_data)

        if child_user:
            parent_user = request.user
            email_user = child_user

        _check_shib_redirect(email_user)
        _check_excessive_login_attempts(email_user)
        _check_forced_password_reset(email_user)

        # set the user object to child_user object if a child is being logged in
        possibly_authenticated_user = email_user

        if not was_authenticated_third_party:
            possibly_authenticated_user = _authenticate_first_party(
                request, post_data, email_user)
            if possibly_authenticated_user and password_policy_compliance.should_enforce_compliance_on_login(
            ):
                # Important: This call must be made AFTER the user was successfully authenticated.
                _enforce_password_policy_compliance(
                    request, post_data, possibly_authenticated_user)

        if possibly_authenticated_user is None or not possibly_authenticated_user.is_active:
            _handle_failed_authentication(email_user)

        _handle_successful_authentication_and_login(
            possibly_authenticated_user, request, post_data)
        if parent_user:
            request.session['parent_user'] = json.dumps({
                'user_id':
                parent_user.id,
                'username':
                parent_user.username,
                'email':
                parent_user.email,
                'name':
                parent_user.profile.name
            })

        redirect_url = None  # The AJAX method calling should know the default destination upon success
        if was_authenticated_third_party:
            running_pipeline = pipeline.get(request)
            redirect_url = pipeline.get_complete_url(
                backend_name=running_pipeline['backend'])

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

        # Ensure that the external marketing site can
        # detect that the user is logged in.
        return set_logged_in_cookies(request, response,
                                     possibly_authenticated_user)
    except AuthFailedError as error:
        return JsonResponse(error.get_response())