def post(self, request): """ Handler for the POST method to this view. """ # The django login method stores the user's id in request.session[SESSION_KEY] and the # path to the user's authentication backend in request.session[BACKEND_SESSION_KEY]. # The login method assumes the backend path had been previously stored in request.user.backend # in the 'authenticate' call. However, not all authentication providers do so. # So we explicitly populate the request.user.backend field here. if not hasattr(request.user, 'backend'): request.user.backend = self._get_path_of_arbitrary_backend_for_user( request.user) if not self._is_grant_password(request.auth): raise AuthenticationFailed({ 'error_code': 'non_supported_token', 'developer_message': 'Only support DOT type access token with grant type password. ' }) login(request, request.user ) # login generates and stores the user's cookies in the session response = HttpResponse( status=204 ) # cookies stored in the session are returned with the response mark_user_change_as_expected(response, request.user.id) return response
def post(self, request): """Create the user's account. You must send all required form fields with the request. You can optionally send a "course_id" param to indicate in analytics events that the user registered while enrolling in a particular course. Arguments: request (HTTPRequest) Returns: HttpResponse: 200 on success HttpResponse: 400 if the request is not valid. HttpResponse: 409 if an account with the given username or email address already exists HttpResponse: 403 operation not allowed """ should_be_rate_limited = getattr(request, 'limited', False) if should_be_rate_limited: return JsonResponse({'error_code': 'forbidden-request'}, status=403) if is_require_third_party_auth_enabled( ) and not pipeline.running(request): # if request is not running a third-party auth pipeline return HttpResponseForbidden( "Third party authentication is required to register. Username and password were received instead." ) data = request.POST.copy() self._handle_terms_of_service(data) response = self._handle_duplicate_email_username(request, data) if response: return response response, user = self._create_account(request, data) if response: return response redirect_to, root_url = get_next_url_for_login_page(request, include_host=True) redirect_url = get_redirect_url_with_host(root_url, redirect_to) response = self._create_response(request, {}, status_code=200, redirect_url=redirect_url) set_logged_in_cookies(request, response, user) if not user.is_active and settings.SHOW_ACCOUNT_ACTIVATION_CTA and not settings.MARKETING_EMAILS_OPT_IN: response.set_cookie( settings.SHOW_ACTIVATE_CTA_POPUP_COOKIE_NAME, True, domain=settings.SESSION_COOKIE_DOMAIN, path='/', secure=request.is_secure() ) # setting the cookie to show account activation dialogue in platform and learning MFE mark_user_change_as_expected(response, user.id) return response
def switch_user(request, lti_user, lti_consumer): """ Log out the current user, and log in using the edX identity associated with the LTI ID. """ edx_user = authenticate(username=lti_user.edx_user.username, lti_user_id=lti_user.lti_user_id, lti_consumer=lti_consumer) if not edx_user: # This shouldn't happen, since we've created edX accounts for any LTI # users by this point, but just in case we can return a 403. raise PermissionDenied() login(request, edx_user) mark_user_change_as_expected(edx_user.id)
def dispatch(self, request, *args, **kwargs): # We do not log here, because we have a handler registered to perform logging on successful logouts. # Get third party auth provider's logout url self.tpa_logout_url = tpa_pipeline.get_idp_logout_url_from_running_pipeline( request) logout(request) response = super().dispatch(request, *args, **kwargs) # Clear the cookie used by the edx.org marketing site delete_logged_in_cookies(response) mark_user_change_as_expected(response, None) return response
def post(self, request): """ Process LTI platform launch requests. """ # Parse LTI launch message. try: self.launch_message = self.get_launch_message() except LtiException as exc: log.exception('LTI 1.3: Tool launch failed: %s', exc) return self._bad_request_response() log.info("LTI 1.3: Launch message body: %s", json.dumps(self.launch_data)) # Parse content key. usage_key_str = request.GET.get('id') if not usage_key_str: return self._bad_request_response() usage_key = LibraryUsageLocatorV2.from_string(usage_key_str) log.info('LTI 1.3: Launch block: id=%s', usage_key) # Authenticate the launch and setup LTI profiles. edx_user = self._authenticate_and_login(usage_key) if not edx_user: return self._bad_request_response() # Get the block. self.block = xblock_api.load_block( usage_key, user=self.request.user) # Handle Assignment and Grade Service request. self.handle_ags() # Render context and response. context = self.get_context_data() response = self.render_to_response(context) mark_user_change_as_expected(edx_user.id) return response
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