Search code examples
djangodjango-allauthdjango-rest-authdjango-oauth

Generate access token using user instance (not username, password and grant_type)


I'm using Django REST Framework and using this library to provide token based authentication to the frontend applications.

There is Login with Google implementation using django-allauth plugin.

I want to generate access token when user login using social account.

For handling social login and generating social account, I have created this view.

class GoogleLoginView(LoginView):
    """
    Enable login using google
    """
    adapter_class = GoogleOAuth2Adapter
    serializer_class = CustomSocialLoginSerializer

    def login(self):
        self.user = self.serializer.validated_data['user']
        self.token = TokenView().create_token_response(self.request)
        return self.token

    def post(self, request, *args, **kwargs):
        self.request = request
        self.serializer = self.get_serializer(
            data=self.request.data,
            context={'request': request}
        )
        self.serializer.is_valid(raise_exception=True)

        url, header, body, status_ = self.login()
        return Response(json.loads(body), status=status_)

The request data has user instance along with client_id and client_secret of the application.

But this gives error

'{"error": "unsupported_grant_type"}'

Version
django-oauth-toolkit==1.3.0


Solution

  • Got it solved by passing client_id and client_secret along with the social network access token and append other fields in the view like

        def login(self):
            self.user = self.serializer.validated_data['user']
    
            # Store request
            request = self.request
    
            # Change request data to mutable
            request.data._mutable = True
    
            # Add required data to the request
            request.data['grant_type'] = 'password'           # Call Password-owned grant type
            request.data['username'] = self.user.username     # Fake request data to oauth-toolkit
            request.data['password'] = '-'                    # Fake request data to oauth-toolkit
            request.data['social_login'] = True               # Important, if not set will use username, password
            request.data['user'] = self.user                  # Important, assign user obj
    
            # Change request data to non-mutable
            request.data._mutable = False
    
            # Generate token
            self.token = TokenView().create_token_response(request)
    
            return self.token