From ece5e48f1c433a9ef847a2f8bd610b2b71e25ce8 Mon Sep 17 00:00:00 2001 From: "hasnain.naveed" Date: Mon, 9 Dec 2019 16:57:21 +0500 Subject: [PATCH] ENT-2505 | By passing the check for forcing the login by third auth when user is already authenticated by third party. --- .../core/djangoapps/user_authn/views/login.py | 10 +- .../user_authn/views/tests/test_login.py | 101 +++++++++++++----- 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/openedx/core/djangoapps/user_authn/views/login.py b/openedx/core/djangoapps/user_authn/views/login.py index 4ebaed3d08..2c5f476cc2 100644 --- a/openedx/core/djangoapps/user_authn/views/login.py +++ b/openedx/core/djangoapps/user_authn/views/login.py @@ -184,7 +184,7 @@ def _log_and_raise_inactive_user_auth_error(unauthenticated_user): raise AuthFailedError(_generate_not_activated_message(unauthenticated_user)) -def _authenticate_first_party(request, unauthenticated_user): +def _authenticate_first_party(request, unauthenticated_user, third_party_auth_requested): """ Use Django authentication on the given request, using rate limiting if configured """ @@ -193,7 +193,11 @@ def _authenticate_first_party(request, unauthenticated_user): # to fail and we can take advantage of the ratelimited backend username = unauthenticated_user.username if unauthenticated_user else "" - _check_user_auth_flow(request.site, unauthenticated_user) + # First time when a user login through third_party_auth account then user needs to link + # third_party account with the platform account by login through email and password that's + # why we need to by-pass this check when user is already authenticated by third_party_auth. + if not third_party_auth_requested: + _check_user_auth_flow(request.site, unauthenticated_user) try: password = normalize_password(request.POST['password']) @@ -372,7 +376,7 @@ def login_user(request): possibly_authenticated_user = user if not is_user_third_party_authenticated: - possibly_authenticated_user = _authenticate_first_party(request, user) + 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) diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_login.py b/openedx/core/djangoapps/user_authn/views/tests/test_login.py index 9245c0a3c9..0cb1c7ea7e 100644 --- a/openedx/core/djangoapps/user_authn/views/tests/test_login.py +++ b/openedx/core/djangoapps/user_authn/views/tests/test_login.py @@ -565,76 +565,123 @@ class LoginTest(SiteMixin, CacheIsolationTestCase): 'whitelisted': False, 'allowed_domain': 'edx.org', 'user_domain': 'edx.org', - 'success': True + 'success': True, + 'is_third_party_authenticated': False }, { 'switch_enabled': False, 'whitelisted': True, 'allowed_domain': 'edx.org', 'user_domain': 'edx.org', - 'success': True + 'success': True, + 'is_third_party_authenticated': False }, { 'switch_enabled': True, 'whitelisted': False, 'allowed_domain': 'edx.org', 'user_domain': 'edx.org', - 'success': False + 'success': False, + 'is_third_party_authenticated': False }, { 'switch_enabled': True, 'whitelisted': False, 'allowed_domain': 'fake.org', 'user_domain': 'edx.org', - 'success': True + 'success': True, + 'is_third_party_authenticated': False }, { 'switch_enabled': True, 'whitelisted': True, 'allowed_domain': 'edx.org', 'user_domain': 'edx.org', - 'success': True + 'success': True, + 'is_third_party_authenticated': False }, { 'switch_enabled': True, 'whitelisted': False, 'allowed_domain': 'batman.gotham', 'user_domain': 'batman.gotham', - 'success': False + 'success': False, + 'is_third_party_authenticated': False + }, + { + 'switch_enabled': True, + 'whitelisted': True, + 'allowed_domain': 'edx.org', + 'user_domain': 'edx.org', + 'success': True, + 'is_third_party_authenticated': True + }, + { + 'switch_enabled': False, + 'whitelisted': False, + 'allowed_domain': 'edx.org', + 'user_domain': 'fake.org', + 'success': True, + 'is_third_party_authenticated': True }, ) @ddt.unpack - def test_login_for_user_auth_flow(self, switch_enabled, whitelisted, allowed_domain, user_domain, success): + def test_login_for_user_auth_flow( + self, + switch_enabled, + whitelisted, + allowed_domain, + user_domain, + success, + is_third_party_authenticated + ): """ Verify that `login._check_user_auth_flow` works as expected. """ + provider = 'Google' username = 'batman' user_email = '{username}@{domain}'.format(username=username, domain=user_domain) user = self._create_user(username, user_email) - - provider = 'Google' - site = self.set_up_site(allowed_domain, { + default_site_configuration_values = { 'SITE_NAME': allowed_domain, 'THIRD_PARTY_AUTH_ONLY_DOMAIN': allowed_domain, - 'THIRD_PARTY_AUTH_ONLY_PROVIDER': provider - }) - - if whitelisted: - AllowedAuthUser.objects.create(site=site, email=user.email) - else: - AllowedAuthUser.objects.filter(site=site, email=user.email).delete() + 'THIRD_PARTY_AUTH_ONLY_PROVIDER': provider, + } with ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY.override(switch_enabled): - value = None if success else u'As an {0} user, You must login with your {0} {1} account.'.format( - allowed_domain, - provider - ) - response, __ = self._login_response(user.email, self.password) - self._assert_response( - response, - success=success, - value=value, - ) + if not is_third_party_authenticated: + site = self.set_up_site(allowed_domain, default_site_configuration_values) + + if whitelisted: + AllowedAuthUser.objects.create(site=site, email=user.email) + else: + AllowedAuthUser.objects.filter(site=site, email=user.email).delete() + + value = None if success else u'As an {0} user, You must login with your {0} {1} account.'.format( + allowed_domain, + provider + ) + response, __ = self._login_response(user.email, self.password) + self._assert_response( + response, + success=success, + value=value, + ) + else: + default_site_configuration_values.update({'ENABLE_THIRD_PARTY_AUTH': True}) + self.set_up_site(allowed_domain, default_site_configuration_values) + with patch('openedx.core.djangoapps.user_authn.views.login.pipeline'): + with patch( + 'openedx.core.djangoapps.user_authn.views.login._check_user_auth_flow' + ) as mock_check_user_auth_flow: + # user is already authenticated by third_party_auth then + # we should by-pass _check_user_auth_flow function + response, __ = self._login_response(user.email, self.password) + self._assert_response( + response, + success=success + ) + self.assertFalse(mock_check_user_auth_flow.called) @ddt.ddt