From 12d1021314f2cc7f3d0d8fe3bece189d0f77f2fd Mon Sep 17 00:00:00 2001 From: jazimmerman Date: Wed, 7 Jun 2023 15:11:07 -0400 Subject: [PATCH 1/2] Added Login on Register and Microsoft Login Serializer --- dj_rest_auth/app_settings.py | 1 + dj_rest_auth/registration/views.py | 55 ++++++++++++++++++++++++++---- dj_rest_auth/social_serializers.py | 43 ++++++++++++++++++++++- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/dj_rest_auth/app_settings.py b/dj_rest_auth/app_settings.py index 949a2a63..1c34a427 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -26,6 +26,7 @@ 'PASSWORD_RESET_USE_SITES_DOMAIN': False, 'OLD_PASSWORD_FIELD_ENABLED': False, 'LOGOUT_ON_PASSWORD_CHANGE': False, + 'LOGIN_ON_REGISTER': False, 'SESSION_LOGIN': True, 'USE_JWT': False, diff --git a/dj_rest_auth/registration/views.py b/dj_rest_auth/registration/views.py index 121f5127..b024df58 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -6,9 +6,11 @@ from allauth.socialaccount import signals from allauth.socialaccount.adapter import get_adapter as get_social_adapter from allauth.socialaccount.models import SocialAccount +from django.utils import timezone from django.utils.decorators import method_decorator from django.utils.translation import gettext_lazy as _ from django.views.decorators.debug import sensitive_post_parameters +from django.contrib.auth import login as django_login from rest_framework import status from rest_framework.exceptions import MethodNotAllowed, NotFound from rest_framework.generics import CreateAPIView, GenericAPIView, ListAPIView @@ -47,28 +49,69 @@ def get_response_data(self, user): return {'detail': _('Verification e-mail sent.')} if api_settings.USE_JWT: + from rest_framework_simplejwt.settings import ( + api_settings as jwt_settings, + ) + access_token_expiration = (timezone.now() + jwt_settings.ACCESS_TOKEN_LIFETIME) + refresh_token_expiration = (timezone.now() + jwt_settings.REFRESH_TOKEN_LIFETIME) + return_expiration_times = api_settings.JWT_AUTH_RETURN_EXPIRATION + auth_httponly = api_settings.JWT_AUTH_HTTPONLY + data = { 'user': user, 'access': self.access_token, - 'refresh': self.refresh_token, } - return api_settings.JWT_SERIALIZER(data, context=self.get_serializer_context()).data + + if not auth_httponly: + data['refresh'] = self.refresh_token + else: + # Wasnt sure if the serializer needed this + data['refresh'] = "" + + if return_expiration_times: + data['access_expiration'] = access_token_expiration + data['refresh_expiration'] = refresh_token_expiration + return api_settings.JWT_SERIALIZER_WITH_EXPIRATION(data, context=self.get_serializer_context()).data + else: + return api_settings.JWT_SERIALIZER(data, context=self.get_serializer_context()).data + elif api_settings.SESSION_LOGIN: return None else: return api_settings.TOKEN_SERIALIZER(user.auth_token, context=self.get_serializer_context()).data + + def get_response(self, data, serializer, *args, **kwargs): + + if api_settings.USE_JWT: + serializer.instance = data, + serializer._context = self.get_serializer_context(), + elif self.token: + serializer.instance = self.token, + serializer._context = self.get_serializer_context(), + else: + return Response(status=status.HTTP_204_NO_CONTENT) + + response = Response(data, status=status.HTTP_201_CREATED) + if api_settings.USE_JWT: + from dj_rest_auth.jwt_auth import set_jwt_cookies + set_jwt_cookies(response, self.access_token, self.refresh_token) + return response + 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) - data = self.get_response_data(user) - if data: + data = self.get_response_data(user) + if api_settings.LOGIN_ON_REGISTER: + response = self.get_response(data, serializer) + response.headers = headers + django_login(self.request, user) + elif data: response = Response( data, - status=status.HTTP_201_CREATED, headers=headers, ) else: @@ -85,7 +128,7 @@ def perform_create(self, serializer): elif not api_settings.SESSION_LOGIN: # Session authentication isn't active either, so this has to be # token authentication - api_settings.TOKEN_CREATOR(self.token_model, user, serializer) + self.token = api_settings.TOKEN_CREATOR(self.token_model, user, serializer) complete_signup( self.request._request, user, diff --git a/dj_rest_auth/social_serializers.py b/dj_rest_auth/social_serializers.py index 494816b3..0501b4ef 100644 --- a/dj_rest_auth/social_serializers.py +++ b/dj_rest_auth/social_serializers.py @@ -10,7 +10,7 @@ from allauth.socialaccount.models import SocialToken from allauth.socialaccount.providers.oauth.client import OAuthError - from dj_rest_auth.registration.serializers import SocialConnectMixin + from dj_rest_auth.registration.serializers import SocialConnectMixin, SocialLoginSerializer class TwitterLoginSerializer(serializers.Serializer): @@ -83,3 +83,44 @@ def validate(self, attrs): class TwitterConnectSerializer(SocialConnectMixin, TwitterLoginSerializer): pass + + +class MicrosoftLoginSerializer(SocialLoginSerializer): + accessToken = serializers.CharField() + + def validate(self, attrs): + view = self.context.get('view') + request = self._get_request() + + if not view: + raise serializers.ValidationError( + 'View is not defined, pass it as a context variable', + ) + + adapter_class = getattr(view, 'adapter_class', None) + if not adapter_class: + raise serializers.ValidationError('Define adapter_class in view') + + adapter = adapter_class(request) + app = adapter.get_provider().get_app(request) + + access_token = attrs.get('accessToken') + + request.session['oauth_api.twitter.com_access_token'] = { + 'oauth_token': access_token, + } + token = SocialToken(token=access_token) + token.app = app + + try: + login = self.get_social_login(adapter, app, token, access_token) + complete_social_login(request, login) + except OAuthError as e: + raise serializers.ValidationError(str(e)) + + if not login.is_existing: + login.lookup() + login.save(request, connect=True) + attrs['user'] = login.account.user + + return attrs From fcfd59d05e2c7713eda381804918b9fccb0d60f5 Mon Sep 17 00:00:00 2001 From: jazimmerman Date: Wed, 7 Jun 2023 15:24:21 -0400 Subject: [PATCH 2/2] removed request.session line --- dj_rest_auth/social_serializers.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/dj_rest_auth/social_serializers.py b/dj_rest_auth/social_serializers.py index 0501b4ef..317fc26d 100644 --- a/dj_rest_auth/social_serializers.py +++ b/dj_rest_auth/social_serializers.py @@ -106,9 +106,6 @@ def validate(self, attrs): access_token = attrs.get('accessToken') - request.session['oauth_api.twitter.com_access_token'] = { - 'oauth_token': access_token, - } token = SocialToken(token=access_token) token.app = app