From 569765639d59da69d18c6a63f41c3160500c4a15 Mon Sep 17 00:00:00 2001 From: Philippe Luickx Date: Fri, 27 May 2016 14:26:44 +0300 Subject: [PATCH 1/9] Checking for pre-existing accounts from a different flow when using social connect --- rest_auth/registration/serializers.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index 9056164..899e74b 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -1,6 +1,7 @@ from django.http import HttpRequest from django.conf import settings from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth import get_user_model try: from allauth.account import app_settings as allauth_settings @@ -109,6 +110,20 @@ class SocialLoginSerializer(serializers.Serializer): raise serializers.ValidationError(_('Incorrect value')) if not login.is_existing: + # We have an account already signed up in a different flow + # with the same email address: raise an exception. + # This needs to be handled in the frontend. We can not just + # link up the accounts due to security constraints + if(allauth_settings.UNIQUE_EMAIL): + # Do we have an account already with this email address? + existing_account = get_user_model().objects.filter( + email=login.user.email, + ).count() + if(existing_account != 0): + # There is an account already + raise serializers.ValidationError( + _("A user is already registered with this e-mail address.")) + login.lookup() login.save(request, connect=True) attrs['user'] = login.account.user From a2f9ca73ee38b038ebda0a4b50c9d5721ee7dbdd Mon Sep 17 00:00:00 2001 From: Philippe Luickx Date: Fri, 27 May 2016 14:26:44 +0300 Subject: [PATCH 2/9] Checking for pre-existing accounts from a different flow when using social connect --- rest_auth/registration/serializers.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index 9056164..899e74b 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -1,6 +1,7 @@ from django.http import HttpRequest from django.conf import settings from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth import get_user_model try: from allauth.account import app_settings as allauth_settings @@ -109,6 +110,20 @@ class SocialLoginSerializer(serializers.Serializer): raise serializers.ValidationError(_('Incorrect value')) if not login.is_existing: + # We have an account already signed up in a different flow + # with the same email address: raise an exception. + # This needs to be handled in the frontend. We can not just + # link up the accounts due to security constraints + if(allauth_settings.UNIQUE_EMAIL): + # Do we have an account already with this email address? + existing_account = get_user_model().objects.filter( + email=login.user.email, + ).count() + if(existing_account != 0): + # There is an account already + raise serializers.ValidationError( + _("A user is already registered with this e-mail address.")) + login.lookup() login.save(request, connect=True) attrs['user'] = login.account.user From fb774109a0530a4508d52d4451f2e538bef3961a Mon Sep 17 00:00:00 2001 From: Philippe Luickx Date: Fri, 27 May 2016 14:26:44 +0300 Subject: [PATCH 3/9] Checking for pre-existing accounts from a different flow when using social connect --- rest_auth/registration/serializers.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index c6b5d5b..61f82dc 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -1,6 +1,7 @@ from django.http import HttpRequest from django.conf import settings from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth import get_user_model try: from allauth.account import app_settings as allauth_settings @@ -111,6 +112,20 @@ class SocialLoginSerializer(serializers.Serializer): raise serializers.ValidationError(_('Incorrect value')) if not login.is_existing: + # We have an account already signed up in a different flow + # with the same email address: raise an exception. + # This needs to be handled in the frontend. We can not just + # link up the accounts due to security constraints + if(allauth_settings.UNIQUE_EMAIL): + # Do we have an account already with this email address? + existing_account = get_user_model().objects.filter( + email=login.user.email, + ).count() + if(existing_account != 0): + # There is an account already + raise serializers.ValidationError( + _("A user is already registered with this e-mail address.")) + login.lookup() login.save(request, connect=True) attrs['user'] = login.account.user From c18771aa8542d631a297a7aa6913a6f68c0690e3 Mon Sep 17 00:00:00 2001 From: Philippe Luickx Date: Thu, 23 Mar 2017 13:54:22 +0200 Subject: [PATCH 4/9] adapted test case and added DRF as pip requirement for tests --- rest_auth/tests/requirements.pip | 1 + rest_auth/tests/test_social.py | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/rest_auth/tests/requirements.pip b/rest_auth/tests/requirements.pip index 5a30385..b86361a 100644 --- a/rest_auth/tests/requirements.pip +++ b/rest_auth/tests/requirements.pip @@ -2,3 +2,4 @@ django-allauth>=0.25.0 responses>=0.3.0 flake8==2.4.0 djangorestframework-jwt>=1.7.2 +djangorestframework>=3.6.2 \ No newline at end of file diff --git a/rest_auth/tests/test_social.py b/rest_auth/tests/test_social.py index 47ac0bb..ab68e13 100644 --- a/rest_auth/tests/test_social.py +++ b/rest_auth/tests/test_social.py @@ -275,8 +275,12 @@ class TestSocialAuth(TestCase, BaseAPITestCase): 'access_token': 'abc123' } - self.post(self.fb_login_url, data=payload, status_code=200) - self.assertIn('key', self.response.json.keys()) + # You should not have access to an account created through register + # by loging in through FB with an account that has the same + # email address. + self.post(self.fb_login_url, data=payload, status_code=400) + # self.post(self.fb_login_url, data=payload, status_code=200) + # self.assertIn('key', self.response.json.keys()) @responses.activate @override_settings( From 95cfe5e07814ac9be09589d96cb42cd4b9f67cb2 Mon Sep 17 00:00:00 2001 From: Philippe Luickx Date: Fri, 27 May 2016 14:26:44 +0300 Subject: [PATCH 5/9] Checking for pre-existing accounts from a different flow when using social connect --- rest_auth/registration/serializers.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index c6b5d5b..61f82dc 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -1,6 +1,7 @@ from django.http import HttpRequest from django.conf import settings from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth import get_user_model try: from allauth.account import app_settings as allauth_settings @@ -111,6 +112,20 @@ class SocialLoginSerializer(serializers.Serializer): raise serializers.ValidationError(_('Incorrect value')) if not login.is_existing: + # We have an account already signed up in a different flow + # with the same email address: raise an exception. + # This needs to be handled in the frontend. We can not just + # link up the accounts due to security constraints + if(allauth_settings.UNIQUE_EMAIL): + # Do we have an account already with this email address? + existing_account = get_user_model().objects.filter( + email=login.user.email, + ).count() + if(existing_account != 0): + # There is an account already + raise serializers.ValidationError( + _("A user is already registered with this e-mail address.")) + login.lookup() login.save(request, connect=True) attrs['user'] = login.account.user From fdf8680b94718532fdc3e3efcb8ad3e169ed51c3 Mon Sep 17 00:00:00 2001 From: Philippe Luickx Date: Thu, 23 Mar 2017 13:54:22 +0200 Subject: [PATCH 6/9] adapted test case and added DRF as pip requirement for tests --- rest_auth/tests/requirements.pip | 1 + rest_auth/tests/test_social.py | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/rest_auth/tests/requirements.pip b/rest_auth/tests/requirements.pip index 5a30385..b86361a 100644 --- a/rest_auth/tests/requirements.pip +++ b/rest_auth/tests/requirements.pip @@ -2,3 +2,4 @@ django-allauth>=0.25.0 responses>=0.3.0 flake8==2.4.0 djangorestframework-jwt>=1.7.2 +djangorestframework>=3.6.2 \ No newline at end of file diff --git a/rest_auth/tests/test_social.py b/rest_auth/tests/test_social.py index 47ac0bb..ab68e13 100644 --- a/rest_auth/tests/test_social.py +++ b/rest_auth/tests/test_social.py @@ -275,8 +275,12 @@ class TestSocialAuth(TestCase, BaseAPITestCase): 'access_token': 'abc123' } - self.post(self.fb_login_url, data=payload, status_code=200) - self.assertIn('key', self.response.json.keys()) + # You should not have access to an account created through register + # by loging in through FB with an account that has the same + # email address. + self.post(self.fb_login_url, data=payload, status_code=400) + # self.post(self.fb_login_url, data=payload, status_code=200) + # self.assertIn('key', self.response.json.keys()) @responses.activate @override_settings( From f40c031c801cb66f1fd03a0101e8fad86ea8fc8a Mon Sep 17 00:00:00 2001 From: Philippe Luickx Date: Fri, 30 Jun 2017 23:07:50 +0300 Subject: [PATCH 7/9] check for is_open_for_signup method in the adapter on register --- rest_auth/registration/views.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/rest_auth/registration/views.py b/rest_auth/registration/views.py index d6638b6..5b56de3 100644 --- a/rest_auth/registration/views.py +++ b/rest_auth/registration/views.py @@ -36,7 +36,14 @@ class RegisterView(CreateAPIView): @sensitive_post_parameters_m def dispatch(self, *args, **kwargs): - return super(RegisterView, self).dispatch(*args, **kwargs) + # Check if registration is open + if get_adapter(self.request).is_open_for_signup(self.request): + return super(RegisterView, self).dispatch(*args, **kwargs) + else: + return Response( + data={'message': 'Registration is not open.'}, + status=status.HTTP_403_FORBIDDEN, + ) def get_response_data(self, user): if allauth_settings.EMAIL_VERIFICATION == \ From 55fa1bbe0edbe11f5ba239393351ed078a7d0395 Mon Sep 17 00:00:00 2001 From: Philippe Luickx Date: Fri, 30 Jun 2017 23:13:01 +0300 Subject: [PATCH 8/9] check is_open_for_signup method on adapter for sociallogin --- rest_auth/registration/views.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rest_auth/registration/views.py b/rest_auth/registration/views.py index 5b56de3..7231180 100644 --- a/rest_auth/registration/views.py +++ b/rest_auth/registration/views.py @@ -25,7 +25,7 @@ from rest_auth.views import LoginView from .app_settings import RegisterSerializer, register_permission_classes sensitive_post_parameters_m = method_decorator( - sensitive_post_parameters('password1', 'password2') + sensitive_post_parameters('password', 'old_password', 'new_password1', 'new_password2', 'password1', 'password2') ) @@ -124,5 +124,16 @@ class SocialLoginView(LoginView): serializer_class = SocialLoginSerializer + @sensitive_post_parameters_m + def dispatch(self, *args, **kwargs): + # Check if registration is open + if get_adapter(self.request).is_open_for_signup(self.request): + return super(SocialLoginView, self).dispatch(*args, **kwargs) + else: + return Response( + data={'message': 'Registration is not open.'}, + status=status.HTTP_403_FORBIDDEN, + ) + def process_login(self): get_adapter(self.request).login(self.request, self.user) From d6ff813e7a642ad22e04772ab14d9a0beb65875d Mon Sep 17 00:00:00 2001 From: Philippe Luickx Date: Mon, 3 Jul 2017 11:20:57 +0300 Subject: [PATCH 9/9] bugfix --- rest_auth/registration/views.py | 45 +++++++++++++-------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/rest_auth/registration/views.py b/rest_auth/registration/views.py index 7231180..c367580 100644 --- a/rest_auth/registration/views.py +++ b/rest_auth/registration/views.py @@ -36,14 +36,7 @@ class RegisterView(CreateAPIView): @sensitive_post_parameters_m def dispatch(self, *args, **kwargs): - # Check if registration is open - if get_adapter(self.request).is_open_for_signup(self.request): - return super(RegisterView, self).dispatch(*args, **kwargs) - else: - return Response( - data={'message': 'Registration is not open.'}, - status=status.HTTP_403_FORBIDDEN, - ) + return super(RegisterView, self).dispatch(*args, **kwargs) def get_response_data(self, user): if allauth_settings.EMAIL_VERIFICATION == \ @@ -60,14 +53,21 @@ class RegisterView(CreateAPIView): return TokenSerializer(user.auth_token).data def create(self, request, *args, **kwargs): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - user = self.perform_create(serializer) - headers = self.get_success_headers(serializer.data) + # Check if registration is open + if get_adapter(self.request).is_open_for_signup(self.request): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = self.perform_create(serializer) + headers = self.get_success_headers(serializer.data) - return Response(self.get_response_data(user), - status=status.HTTP_201_CREATED, - headers=headers) + return Response(self.get_response_data(user), + status=status.HTTP_201_CREATED, + headers=headers) + else: + return Response( + data={'message': 'Registration is not open.'}, + status=status.HTTP_403_FORBIDDEN, + ) def perform_create(self, serializer): user = serializer.save(self.request) @@ -117,23 +117,12 @@ class SocialLoginView(LoginView): class FacebookLogin(SocialLoginView): adapter_class = FacebookOAuth2Adapter - client_class = OAuth2Client - callback_url = 'localhost:8000' + client_class = OAuth2Client + callback_url = 'localhost:8000' ------------- """ serializer_class = SocialLoginSerializer - @sensitive_post_parameters_m - def dispatch(self, *args, **kwargs): - # Check if registration is open - if get_adapter(self.request).is_open_for_signup(self.request): - return super(SocialLoginView, self).dispatch(*args, **kwargs) - else: - return Response( - data={'message': 'Registration is not open.'}, - status=status.HTTP_403_FORBIDDEN, - ) - def process_login(self): get_adapter(self.request).login(self.request, self.user)