def test_already_associated_exception_populates_dashboard_with_error(self): # Instrument the pipeline with an exception. We test that the # exception is raised correctly separately, so it's ok that we're # raising it artificially here. This makes the linked=True artificial # in the final assert because in practice the account would be # unlinked, but getting that behavior is cumbersome here and already # covered in other tests. Using linked=True does, however, let us test # that the duplicate error has no effect on the state of the controls. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) self.client.get('/login') self.client.get(pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access request=request) with self._patch_edxmako_current_request(strategy.request): signin_user(strategy.request) login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access user=user, request=request) # Monkey-patch storage for messaging; pylint: disable=protected-access request._messages = fallback.FallbackStorage(request) middleware.ExceptionMiddleware().process_exception( request, exceptions.AuthAlreadyAssociated(self.provider.backend_name, 'account is already in use.')) self.assert_account_settings_context_looks_correct( account_settings_context(request), duplicate=True, linked=True)
def test_already_associated_exception_populates_dashboard_with_error(self): # Instrument the pipeline with an exception. We test that the # exception is raised correctly separately, so it's ok that we're # raising it artificially here. This makes the linked=True artificial # in the final assert because in practice the account would be # unlinked, but getting that behavior is cumbersome here and already # covered in other tests. Using linked=True does, however, let us test # that the duplicate error has no effect on the state of the controls. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) self.client.get('/login') self.client.get(pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access request=request) with self._patch_edxmako_current_request(strategy.request): signin_user(strategy.request) login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access user=user, request=request) # Monkey-patch storage for messaging; pylint: disable=protected-access request._messages = fallback.FallbackStorage(request) middleware.ExceptionMiddleware().process_exception( request, exceptions.AuthAlreadyAssociated(self.provider.backend_name, 'account is already in use.')) self.assert_account_settings_context_looks_correct( account_settings_context(request), duplicate=True, linked=True)
def test_full_pipeline_succeeds_for_signing_in_to_existing_active_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) pipeline.analytics.track = mock.MagicMock() user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) self.assertTrue(user.is_active) # Begin! Ensure that the login form contains expected controls before # the user starts the pipeline. self.assert_login_response_before_pipeline_looks_correct(self.client.get('/login')) # The pipeline starts by a user GETting /auth/login/<provider>. # Synthesize that request and check that it redirects to the correct # provider page. self.assert_redirect_to_provider_looks_correct(self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN))) # Next, the provider makes a request against /auth/complete/<provider> # to resume the pipeline. # pylint: disable=protected-access self.assert_redirect_to_login_looks_correct(actions.do_complete(request.backend, social_views._do_login, request=request)) # At this point we know the pipeline has resumed correctly. Next we # fire off the view that displays the login form and posts it via JS. with self._patch_edxmako_current_request(strategy.request): self.assert_login_response_in_pipeline_looks_correct(signin_user(strategy.request)) # Next, we invoke the view that handles the POST, and expect it # redirects to /auth/complete. In the browser ajax handlers will # redirect the user to the dashboard; we invoke it manually here. self.assert_json_success_response_looks_correct(login_user(strategy.request)) # We should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request )) # Set the cookie and try again self.set_logged_in_cookies(request) self.assert_redirect_to_dashboard_looks_correct( actions.do_complete(request.backend, social_views._do_login, user=user, request=request)) self.assert_account_settings_context_looks_correct(account_settings_context(request))
def test_full_pipeline_succeeds_for_signing_in_to_existing_active_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) pipeline.analytics.track = mock.MagicMock() user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) self.assertTrue(user.is_active) # Begin! Ensure that the login form contains expected controls before # the user starts the pipeline. self.assert_login_response_before_pipeline_looks_correct(self.client.get('/login')) # The pipeline starts by a user GETting /auth/login/<provider>. # Synthesize that request and check that it redirects to the correct # provider page. self.assert_redirect_to_provider_looks_correct(self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN))) # Next, the provider makes a request against /auth/complete/<provider> # to resume the pipeline. # pylint: disable=protected-access self.assert_redirect_to_login_looks_correct(actions.do_complete(request.backend, social_views._do_login, request=request)) # At this point we know the pipeline has resumed correctly. Next we # fire off the view that displays the login form and posts it via JS. with self._patch_edxmako_current_request(strategy.request): self.assert_login_response_in_pipeline_looks_correct(signin_user(strategy.request)) # Next, we invoke the view that handles the POST, and expect it # redirects to /auth/complete. In the browser ajax handlers will # redirect the user to the dashboard; we invoke it manually here. self.assert_json_success_response_looks_correct(login_user(strategy.request)) # We should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request )) # Set the cookie and try again self.set_logged_in_cookies(request) self.assert_redirect_to_dashboard_looks_correct( actions.do_complete(request.backend, social_views._do_login, user=user, request=request)) self.assert_account_settings_context_looks_correct(account_settings_context(request))
def custom_complete(request, backend, u_hash, u_hash_sess, *args, **kwargs): """Authentication complete view""" if u_hash and u_hash == u_hash_sess: # if invited tester join course - create user immediately without confirmation email. data = request.POST.dict().copy() user = request.backend.strategy.create_user(**data) user.backend = 'django.contrib.auth.backends.ModelBackend' user = authenticate(username=user.username, password=data.get('password')) login(request, user) request.session['u_hash'] = u_hash response = do_complete( request.backend, _do_login, request.user, redirect_name=REDIRECT_FIELD_NAME, *args, **kwargs) if not u_hash or u_hash != u_hash_sess: # if not invited tester join course - logout user logout(request) # add resend_user_email to the session to be able to resend link request.session['resend_user_email'] = request.POST.get('email') # getting just created CustomCode cc = CustomCode.objects.filter(email=request.POST.get('email')).order_by('-id').first() if cc: request.session['cc_id'] = cc.id # remove u_hash from session request.session.pop('u_hash', None) if request.user.is_authenticated(): Profile.check_tz(request) return response
def _complete(self, backend, *args, **kwargs): return do_complete( self.backend, login=lambda backend, user, social_user: self.login_user(user), user=self.get_current_user(), *args, **kwargs)
def complete_view(request, backend, *args, **kwargs): # Check if ADFS doesn't allow access to the Service if 'SAMLResponse' in request.POST: saml_response_encoded = request.POST['SAMLResponse'] saml_response_string = base64.b64decode(saml_response_encoded).decode( 'utf-8') if 'samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:RequestDenied"' in saml_response_string: storage = messages.get_messages(request) storage.used = True messages.error( request, "Пользователь не имеет доступа к системе. Убедитесь в том, что пользователю присвоены права доступа в ADFS." ) return HttpResponseRedirect( reverse(getattr(settings, 'SOCIAL_AUTH_SAML_LOGIN', 'login'))) # Если в системе залогинен один пользователь, а другой пытается залогиниться, # social auth кинет из пайплайна эксепшен об этом. Если пайплайн переопределить # и убрать эксепшен, вход вообще не будте работать, потому что do_complete # при виде влогиненного request_user'а просто не вызывает login для нового. # Так что... # Говорим social auth'у, что в рекветсе не было пользователя, так всё вроде ок. request_user = None # request.user set_user_login_details(request, 'SAML', True) return do_complete(request.backend, _do_login, request_user, redirect_name=REDIRECT_FIELD_NAME, request=request, *args, **kwargs)
def complete(request: HttpRequest, backend: str, *args, **kwargs) -> HttpResponse: """ Authentication complete view with custom _do_login method, saving token to session link """ return do_complete(request.backend, _do_save_session_login, request.user, redirect_name=REDIRECT_FIELD_NAME, request=request, *args, **kwargs)
def complete(request, backend, *args, **kwargs): """Authentication complete view""" print(request.user) request.session['username'] = request.user.username return do_complete(request.backend, _do_login, request.user, redirect_name=REDIRECT_FIELD_NAME, *args, **kwargs)
def complete(request, backend, *args, **kwargs): """Authentication complete view""" return do_complete(request.backend, _do_login, request.user, redirect_name=REDIRECT_FIELD_NAME, *args, **kwargs)
def complete(request, *args, **kwargs): do_login = module_member(request.backend.setting('LOGIN_FUNCTION')) return do_complete(request.backend, do_login, request.user, redirect_name='next', *args, **kwargs)
def complete(backend, *args, **kwargs): """Authentication complete view, override this view if transaction management doesn't suit your needs.""" return do_complete(g.backend, login=do_login, user=current_user, *args, **kwargs)
def complete(request, backend, *args, **kwargs): return do_complete(request.backend, _do_login, request.user, redirect_value='next', request=request, *args, **kwargs)
def complete(request, backend, *args, **kwargs): return do_complete( request.backend, do_login, user=request.user, redirect_name=REDIRECT_FIELD_NAME, request=request, *args, **kwargs )
def test_full_pipeline_succeeds_for_unlinking_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) # We're already logged in, so simulate that the cookie is set correctly self.set_logged_in_cookies(request) # Instrument the pipeline to get to the dashboard with the full # expected state. self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access request=request) with self._patch_edxmako_current_request(strategy.request): signin_user(strategy.request) login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, user=user, # pylint: disable=protected-access request=request) # First we expect that we're in the linked state, with a backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=True) self.assert_social_auth_exists_for_user(request.user, strategy) # Fire off the disconnect pipeline to unlink. self.assert_redirect_to_dashboard_looks_correct( actions.do_disconnect( request.backend, request.user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME ) ) # Now we expect to be in the unlinked state, with no backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=False) self.assert_social_auth_does_not_exist_for_user(user, strategy)
def test_full_pipeline_succeeds_for_unlinking_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) # We're already logged in, so simulate that the cookie is set correctly self.set_logged_in_cookies(request) # Instrument the pipeline to get to the dashboard with the full # expected state. self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access request=request) with self._patch_edxmako_current_request(strategy.request): signin_user(strategy.request) login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, user=user, # pylint: disable=protected-access request=request) # First we expect that we're in the linked state, with a backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=True) self.assert_social_auth_exists_for_user(request.user, strategy) # Fire off the disconnect pipeline to unlink. self.assert_redirect_after_pipeline_completes( actions.do_disconnect( request.backend, request.user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME ) ) # Now we expect to be in the unlinked state, with no backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=False) self.assert_social_auth_does_not_exist_for_user(user, strategy)
def complete(request, backend, *args, **kwargs): print('======comp2') print(request.__dict__) """Authentication complete view""" return do_complete(request.backend, _do_login, request.user, redirect_name=REDIRECT_FIELD_NAME, request=request, *args, **kwargs)
def callback(self, state_token, authz_code, trans, login_redirect_url): self._on_the_fly_config(trans) self.config[setting_name('LOGIN_REDIRECT_URL')] = login_redirect_url strategy = Strategy(trans, Storage, self.config) strategy.session_set(BACKENDS_NAME[self.config['provider']] + '_state', state_token) backend = self._load_backend(strategy, self.config['redirect_uri']) redirect_url = do_complete( backend, login=lambda backend, user, social_user: self._login_user(backend, user, social_user), user=self._get_current_user(trans), state=state_token) return redirect_url, self.config.get('user', None)
def callback(self, state_token, authz_code, trans, login_redirect_url): on_the_fly_config(trans.sa_session) self.config[setting_name('LOGIN_REDIRECT_URL')] = login_redirect_url strategy = Strategy(trans.request, trans.session, Storage, self.config) strategy.session_set(BACKENDS_NAME[self.config['provider']] + '_state', state_token) backend = self._load_backend(strategy, self.config['redirect_uri']) redirect_url = do_complete( backend, login=lambda backend, user, social_user: self._login_user(backend, user, social_user), user=trans.user, state=state_token) return redirect_url, self.config.get('user', None)
def login_done(request, backend, *args, **kwargs): if request.user.is_authenticated: return complete(request, backend, *args, **kwargs) else: try: return do_complete(request, backend, *args, **kwargs) except Exception as e: logger.exception(e) return html_response('login.html', { 'at_login': True, 'error': str(e) }, request)
def mfa_reset_complete(request,backend,*args,**kwargs): """ View method for path '/sso/mfa/set/complete' Callback url from b2c to complete a user mfa set request """ domain = utils.get_redirect_domain(request) request.policy = models.CustomizableUserflow.get_userflow(domain).mfa_reset request.http_error_code = 417 request.http_error_message = "Failed to set mfa method.{}" return do_complete(request.backend, _do_login, user=request.user, redirect_name=REDIRECT_FIELD_NAME, request=request, *args, **kwargs)
def test_linking_already_associated_account_raises_auth_already_associated(self): # This is of a piece with # test_already_associated_exception_populates_dashboard_with_error. It # verifies the exception gets raised when we expect; the latter test # covers exception handling. email = '*****@*****.**' password = '******' username = self.get_username() _, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') backend = strategy.request.backend backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) linked_user = self.create_user_models_for_existing_account(strategy, email, password, username) unlinked_user = social_utils.Storage.user.create_user( email='other_' + email, password=password, username='******' + username) self.assert_social_auth_exists_for_user(linked_user, strategy) self.assert_social_auth_does_not_exist_for_user(unlinked_user, strategy) with self.assertRaises(exceptions.AuthAlreadyAssociated): # pylint: disable=protected-access actions.do_complete(backend, social_views._do_login, user=unlinked_user, request=strategy.request)
def complete(): # Store "next" value in session _next = current.request.vars.get('next', None) if _next: current.strategy.session_set('next', _next) try: return do_complete(current.backend, login=lambda strat, user, social_user: login_user(user.row), user=get_current_user()) except Exception as e: process_exception(e) return
def test_linking_already_associated_account_raises_auth_already_associated(self): # This is of a piece with # test_already_associated_exception_populates_dashboard_with_error. It # verifies the exception gets raised when we expect; the latter test # covers exception handling. email = '*****@*****.**' password = '******' username = self.get_username() _, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') backend = strategy.request.backend backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) linked_user = self.create_user_models_for_existing_account(strategy, email, password, username) unlinked_user = social_utils.Storage.user.create_user( email='other_' + email, password=password, username='******' + username) self.assert_social_auth_exists_for_user(linked_user, strategy) self.assert_social_auth_does_not_exist_for_user(unlinked_user, strategy) with self.assertRaises(exceptions.AuthAlreadyAssociated): # pylint: disable=protected-access actions.do_complete(backend, social_views._do_login, user=unlinked_user, request=strategy.request)
def test_pipeline_redirects_to_requested_url(self): requested_redirect_url = 'foo' # something different from '/dashboard' request, strategy = self.get_request_and_strategy(redirect_uri='social:complete') strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) request.session[pipeline.AUTH_REDIRECT_KEY] = requested_redirect_url user = self.create_user_models_for_existing_account(strategy, '*****@*****.**', 'password', self.get_username()) self.set_logged_in_cookies(request) self.assert_redirect_after_pipeline_completes( actions.do_complete(request.backend, social_views._do_login, user=user, request=request), # pylint: disable=protected-access requested_redirect_url, )
def test_pipeline_redirects_to_requested_url(self): requested_redirect_url = 'foo' # something different from '/dashboard' request, strategy = self.get_request_and_strategy(redirect_uri='social:complete') strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) request.session[pipeline.AUTH_REDIRECT_KEY] = requested_redirect_url user = self.create_user_models_for_existing_account(strategy, '*****@*****.**', 'password', self.get_username()) self.set_logged_in_cookies(request) self.assert_redirect_after_pipeline_completes( actions.do_complete(request.backend, social_views._do_login, user=user, request=request), # pylint: disable=protected-access requested_redirect_url, )
def test_new_account_registration_assigns_distinct_username_on_collision(self): original_username = self.get_username() request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_REGISTER, redirect_uri='social:complete') # Create a colliding username in the backend, then proceed with # assignment via pipeline to make sure a distinct username is created. strategy.storage.user.create_user(username=self.get_username(), email='*****@*****.**', password='******') backend = strategy.request.backend backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) # pylint: disable=protected-access self.assert_redirect_to_register_looks_correct(actions.do_complete(backend, social_views._do_login)) distinct_username = pipeline.get(request)['kwargs']['username'] self.assertNotEqual(original_username, distinct_username)
def complete(): # Store "next" value in session _next = current.request.vars.get('next', None) if _next: current.strategy.session_set('next', _next) try: return do_complete( current.backend, login=lambda strat, user, social_user: login_user(user.row), user=get_current_user()) except Exception as e: process_exception(e) return
def test_new_account_registration_assigns_distinct_username_on_collision(self): original_username = self.get_username() request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_REGISTER, redirect_uri='social:complete') # Create a colliding username in the backend, then proceed with # assignment via pipeline to make sure a distinct username is created. strategy.storage.user.create_user(username=self.get_username(), email='*****@*****.**', password='******') backend = strategy.request.backend backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) # pylint: disable=protected-access self.assert_redirect_to_register_looks_correct(actions.do_complete(backend, social_views._do_login)) distinct_username = pipeline.get(request)['kwargs']['username'] self.assertNotEqual(original_username, distinct_username)
def complete(request, provider): redirect_uri = reverse("social:complete", args=(provider, )) request.social_strategy = DjangoStrategy(DjangoStorage, request) try: backend_cls = get_backend(BACKENDS, provider) backend_obj = backend_cls(request.social_strategy, redirect_uri) except MissingBackend: raise Http404('Backend not found') return do_complete(backend_obj, login_func, request.user, redirect_name=REDIRECT_FIELD_NAME, request=request)
def complete(request, backend, *args, **kwargs): """Authentication complete view OVERRIDE Arguments: request {Request} -- Request from Browser backend {string} -- Authentication Backend """ return do_complete(request.backend, _do_login, user=None, redirect_name=REDIRECT_FIELD_NAME, request=request, *args, **kwargs)
def test_full_pipeline_succeeds_for_linking_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) pipeline.analytics.track = mock.MagicMock() request.user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username(), skip_social_auth=True) # Instrument the pipeline to get to the dashboard with the full # expected state. self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access request=request) signin_user(strategy.request) login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access request=request) # First we expect that we're in the unlinked state, and that there # really is no association in the backend. self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=False) self.assert_social_auth_does_not_exist_for_user(request.user, strategy) # We should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request )) # Set the cookie and try again self.set_logged_in_cookies(request) # Fire off the auth pipeline to link. self.assert_redirect_to_dashboard_looks_correct( actions.do_complete( request.backend, social_views._do_login, # pylint: disable=protected-access request.user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request ) ) # Now we expect to be in the linked state, with a backend entry. self.assert_social_auth_exists_for_user(request.user, strategy) self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=True)
def test_full_pipeline_succeeds_for_linking_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) pipeline.analytics.track = mock.MagicMock() request.user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username(), skip_social_auth=True) # Instrument the pipeline to get to the dashboard with the full # expected state. self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access request=request) signin_user(strategy.request) login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access request=request) # First we expect that we're in the unlinked state, and that there # really is no association in the backend. self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=False) self.assert_social_auth_does_not_exist_for_user(request.user, strategy) # We should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request )) # Set the cookie and try again self.set_logged_in_cookies(request) # Fire off the auth pipeline to link. self.assert_redirect_to_dashboard_looks_correct( actions.do_complete( request.backend, social_views._do_login, # pylint: disable=protected-access request.user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request ) ) # Now we expect to be in the linked state, with a backend entry. self.assert_social_auth_exists_for_user(request.user, strategy) self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=True)
def test_new_account_registration_fails_if_email_exists(self): request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_REGISTER, redirect_uri='social:complete') backend = strategy.request.backend backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) # pylint: disable=protected-access self.assert_redirect_to_register_looks_correct(actions.do_complete(backend, social_views._do_login)) with self._patch_edxmako_current_request(request): self.assert_register_response_in_pipeline_looks_correct( student_views.register_user(strategy.request), pipeline.get(request)['kwargs'], ['name', 'username', 'email'] ) with self._patch_edxmako_current_request(strategy.request): strategy.request.POST = self.get_registration_post_vars() # Create twice: once successfully, and once causing a collision. student_views.create_account(strategy.request) self.assert_json_failure_response_is_username_collision(student_views.create_account(strategy.request))
def test_new_account_registration_fails_if_email_exists(self): request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_REGISTER, redirect_uri='social:complete') backend = strategy.request.backend backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) # pylint: disable=protected-access self.assert_redirect_to_register_looks_correct(actions.do_complete(backend, social_views._do_login)) with self._patch_edxmako_current_request(request): self.assert_register_response_in_pipeline_looks_correct( student_views.register_user(strategy.request), pipeline.get(request)['kwargs'], ['name', 'username', 'email'] ) with self._patch_edxmako_current_request(strategy.request): strategy.request.POST = self.get_registration_post_vars() # Create twice: once successfully, and once causing a collision. student_views.create_account(strategy.request) self.assert_json_failure_response_is_username_collision(student_views.create_account(strategy.request))
def complete(request, backend, *args, **kwargs): """Authentication complete view""" print("Actually in complete view") log.debug("In view 'complete'") log.debug("request: {}".format(request)) log.debug("backend: {}".format(backend)) log.debug("args: {}".format(args)) log.debug("kwargs: {}".format(kwargs)) log.debug("request.user starts with {}".format(request.user)) rv = do_complete(request.backend, _do_login, request.user, redirect_name=REDIRECT_FIELD_NAME, request=request, *args, **kwargs) log.debug("do_complete() returned {}".format(rv)) log.debug("request.user ends with {}".format(request.user)) log.debug("session_id is {}".format(request.session.session_key)) log.debug("session is {}".format(dict(request.session))) return rv
def _complete(self, app): self.init_auth(app) # Hack for passing SSO setattr(self.backend, 'sso', app) result = do_complete(self.backend, login=lambda: None) success = result and result.get('auth') auth_uri = configuration.session_get(self.request, AUTH_URI_KEY, '/api/') project = configuration.session_get(self.request, PROJECT_KEY) redirect_uri = configuration.session_get(self.request, REDIRECT_URI_KEY) data = { 'sso': app, 'token': settings.TOKEN, 'project': project, 'redirect_uri': redirect_uri } if success: data['result'] = True data['username'] = result['details'].get('username') data['email'] = result['details'].get('email') data['first_name'] = result['details'].get('first_name') data['last_name'] = result['details'].get('last_name') data['full_name'] = result['details'].get('fullname') else: data['result'] = False data['error'] = 'Authentication failed' return TemplateResponse( 'external_auth_complete.html', status=200, data={'context': json.dumps({ 'url': auth_uri, 'data': data })})
def rest_api_complete(request, backend, *args, **kwargs): """Authentication complete view""" # The social_django do_complete function returns settings.LOGIN_REDIRECT_URL if no next # parameter is given. For the API, a different default redirect_url is needed, but # social_django only allows a single default. Also, the token should be added to the # redirect url. redirect_url = request.session.get("next", "/") result = do_complete( request.backend, _do_login, request.user, redirect_name=REDIRECT_FIELD_NAME, request=request, *args, **kwargs, ) token, created = Token.objects.get_or_create(user=request.user) # For the API, the session is not needed: the token is all that is needed. logout(request) return HttpResponseRedirect(redirect_url + "?token={}".format(token))
def complete(request, backend, *args, **kwargs): """Authentication complete view""" if isinstance(request.backend, MultiTenantMixin): # Get tenant name from session storage saved_tenant = request.backend.strategy.session_get('tenant') if saved_tenant is None: log.error('Session contains no value for "tenant".') return redirect('accounts:login') try: # Setting the tenant on the backend performs normalization and validation of tenant # Part of the validation is that the provided tenant is in the MULTI_TENANT setting. request.backend.tenant = saved_tenant except (ImproperlyConfigured, ValueError) as e: log.error(str(e)) return redirect('accounts:login') return do_complete(request.backend, _do_login, user=request.user, redirect_name=REDIRECT_FIELD_NAME, request=request, *args, **kwargs)
def test_full_pipeline_succeeds_registering_new_account(self): # First, create, the request and strategy that store pipeline state. # Mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_REGISTER, redirect_uri='social:complete') strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) # Begin! Grab the registration page and check the login control on it. self.assert_register_response_before_pipeline_looks_correct(self.client.get('/register')) # The pipeline starts by a user GETting /auth/login/<provider>. # Synthesize that request and check that it redirects to the correct # provider page. self.assert_redirect_to_provider_looks_correct(self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN))) # Next, the provider makes a request against /auth/complete/<provider>. # pylint: disable=protected-access self.assert_redirect_to_register_looks_correct(actions.do_complete(request.backend, social_views._do_login, request=request)) # At this point we know the pipeline has resumed correctly. Next we # fire off the view that displays the registration form. with self._patch_edxmako_current_request(request): self.assert_register_response_in_pipeline_looks_correct( register_user(strategy.request), pipeline.get(request)['kwargs'], ['name', 'username', 'email'] ) # Next, we invoke the view that handles the POST. Not all providers # supply email. Manually add it as the user would have to; this # also serves as a test of overriding provider values. Always provide a # password for us to check that we override it properly. overridden_password = strategy.request.POST.get('password') email = '*****@*****.**' if not strategy.request.POST.get('email'): strategy.request.POST = self.get_registration_post_vars({'email': email}) # The user must not exist yet... with self.assertRaises(auth_models.User.DoesNotExist): self.get_user_by_email(strategy, email) # ...but when we invoke create_account the existing edX view will make # it, but not social auths. The pipeline creates those later. with self._patch_edxmako_current_request(strategy.request): self.assert_json_success_response_looks_correct(create_account(strategy.request)) # We've overridden the user's password, so authenticate() with the old # value won't work: created_user = self.get_user_by_email(strategy, email) self.assert_password_overridden_by_pipeline(overridden_password, created_user.username) # At this point the user object exists, but there is no associated # social auth. self.assert_social_auth_does_not_exist_for_user(created_user, strategy) # We should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request )) # Set the cookie and try again self.set_logged_in_cookies(request) self.assert_redirect_to_dashboard_looks_correct( actions.do_complete(strategy.request.backend, social_views._do_login, user=created_user, request=request)) # Now the user has been redirected to the dashboard. Their third party account should now be linked. self.assert_social_auth_exists_for_user(created_user, strategy) self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=True)
def complete(request, backend, *args, **kwargs): """Authentication complete view""" return do_complete(request.backend, _do_login, request.user, redirect_name=REDIRECT_FIELD_NAME, *args, **kwargs)
def test_full_pipeline_succeeds_for_unlinking_testshib_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. self.provider = self._configure_testshib_provider() request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') request.backend.auth_complete = MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) request.user = user # We're already logged in, so simulate that the cookie is set correctly self.set_logged_in_cookies(request) # linking a learner with enterprise customer. enterprise_customer = EnterpriseCustomerFactory() assert EnterpriseCustomerUser.objects.count() == 0, "Precondition check: no link records should exist" EnterpriseCustomerUser.objects.link_user(enterprise_customer, user.email) self.assertTrue( EnterpriseCustomerUser.objects.filter(enterprise_customer=enterprise_customer, user_id=user.id).count() == 1 ) EnterpriseCustomerIdentityProvider.objects.get_or_create(enterprise_customer=enterprise_customer, provider_id=self.provider.provider_id) # Instrument the pipeline to get to the dashboard with the full expected state. self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access request=request) with self._patch_edxmako_current_request(strategy.request): signin_user(strategy.request) login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, user=user, # pylint: disable=protected-access request=request) # First we expect that we're in the linked state, with a backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=True) self.assert_social_auth_exists_for_user(request.user, strategy) # Fire off the disconnect pipeline without the user information. actions.do_disconnect( request.backend, None, None, redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request ) self.assertFalse( EnterpriseCustomerUser.objects.filter(enterprise_customer=enterprise_customer, user_id=user.id).count() == 0 ) # Fire off the disconnect pipeline to unlink. self.assert_redirect_to_dashboard_looks_correct( actions.do_disconnect( request.backend, user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request ) ) # Now we expect to be in the unlinked state, with no backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=False) self.assert_social_auth_does_not_exist_for_user(user, strategy) self.assertTrue( EnterpriseCustomerUser.objects.filter(enterprise_customer=enterprise_customer, user_id=user.id).count() == 0 )
def complete(request, backend, *args, **kwargs): return do_complete(request.backend, _do_login, request.user, redirect_value='next', request=request, *args, **kwargs)
def test_full_pipeline_succeeds_for_unlinking_testshib_account( self, mock_get_enterprise_customer_for_learner_settings_view, mock_get_enterprise_customer_for_learner, mock_enterprise_customer_for_request, ): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. self.provider = self._configure_testshib_provider() request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') request.backend.auth_complete = MagicMock( return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) request.user = user # We're already logged in, so simulate that the cookie is set correctly self.set_logged_in_cookies(request) # linking a learner with enterprise customer. enterprise_customer = EnterpriseCustomerFactory() assert EnterpriseCustomerUser.objects.count( ) == 0, "Precondition check: no link records should exist" EnterpriseCustomerUser.objects.link_user(enterprise_customer, user.email) self.assertTrue( EnterpriseCustomerUser.objects.filter( enterprise_customer=enterprise_customer, user_id=user.id).count() == 1) EnterpriseCustomerIdentityProvider.objects.get_or_create( enterprise_customer=enterprise_customer, provider_id=self.provider.provider_id) enterprise_customer_data = { 'uuid': enterprise_customer.uuid, 'name': enterprise_customer.name, 'identity_provider': 'saml-default', } mock_enterprise_customer_for_request.return_value = enterprise_customer_data mock_get_enterprise_customer_for_learner.return_value = enterprise_customer_data mock_get_enterprise_customer_for_learner_settings_view.return_value = enterprise_customer_data # Instrument the pipeline to get to the dashboard with the full expected state. self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete( request.backend, social_views._do_login, # pylint: disable=protected-access request=request) with self._patch_edxmako_current_request(strategy.request): login_user(strategy.request) actions.do_complete( request.backend, social_views._do_login, user=user, # pylint: disable=protected-access request=request) # First we expect that we're in the linked state, with a backend entry. self.assert_account_settings_context_looks_correct( account_settings_context(request), linked=True) self.assert_social_auth_exists_for_user(request.user, strategy) FEATURES_WITH_ENTERPRISE_ENABLED = settings.FEATURES.copy() FEATURES_WITH_ENTERPRISE_ENABLED[ 'ENABLE_ENTERPRISE_INTEGRATION'] = True with patch.dict("django.conf.settings.FEATURES", FEATURES_WITH_ENTERPRISE_ENABLED): # Fire off the disconnect pipeline without the user information. actions.do_disconnect(request.backend, None, None, redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request) self.assertNotEqual( EnterpriseCustomerUser.objects.filter( enterprise_customer=enterprise_customer, user_id=user.id).count(), 0) # Fire off the disconnect pipeline to unlink. self.assert_redirect_after_pipeline_completes( actions.do_disconnect( request.backend, user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request)) # Now we expect to be in the unlinked state, with no backend entry. self.assert_account_settings_context_looks_correct( account_settings_context(request), linked=False) self.assert_social_auth_does_not_exist_for_user(user, strategy) self.assertEqual( EnterpriseCustomerUser.objects.filter( enterprise_customer=enterprise_customer, user_id=user.id).count(), 0)
def test_full_pipeline_succeeds_registering_new_account(self): # First, create, the request and strategy that store pipeline state. # Mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_REGISTER, redirect_uri='social:complete') strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) # Begin! Grab the registration page and check the login control on it. self.assert_register_response_before_pipeline_looks_correct(self.client.get('/register')) # The pipeline starts by a user GETting /auth/login/<provider>. # Synthesize that request and check that it redirects to the correct # provider page. self.assert_redirect_to_provider_looks_correct(self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN))) # Next, the provider makes a request against /auth/complete/<provider>. # pylint: disable=protected-access self.assert_redirect_to_register_looks_correct(actions.do_complete(request.backend, social_views._do_login, request=request)) # At this point we know the pipeline has resumed correctly. Next we # fire off the view that displays the registration form. with self._patch_edxmako_current_request(request): self.assert_register_response_in_pipeline_looks_correct( register_user(strategy.request), pipeline.get(request)['kwargs'], ['name', 'username', 'email'] ) # Next, we invoke the view that handles the POST. Not all providers # supply email. Manually add it as the user would have to; this # also serves as a test of overriding provider values. Always provide a # password for us to check that we override it properly. overridden_password = strategy.request.POST.get('password') email = '*****@*****.**' if not strategy.request.POST.get('email'): strategy.request.POST = self.get_registration_post_vars({'email': email}) # The user must not exist yet... with self.assertRaises(auth_models.User.DoesNotExist): self.get_user_by_email(strategy, email) # ...but when we invoke create_account the existing edX view will make # it, but not social auths. The pipeline creates those later. with self._patch_edxmako_current_request(strategy.request): self.assert_json_success_response_looks_correct(create_account(strategy.request)) # We've overridden the user's password, so authenticate() with the old # value won't work: created_user = self.get_user_by_email(strategy, email) self.assert_password_overridden_by_pipeline(overridden_password, created_user.username) # At this point the user object exists, but there is no associated # social auth. self.assert_social_auth_does_not_exist_for_user(created_user, strategy) # We should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request )) # Set the cookie and try again self.set_logged_in_cookies(request) self.assert_redirect_after_pipeline_completes( actions.do_complete(strategy.request.backend, social_views._do_login, user=created_user, request=request)) # Now the user has been redirected to the dashboard. Their third party account should now be linked. self.assert_social_auth_exists_for_user(created_user, strategy) self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=True)