Search code examples
oauth-2.0django-rest-framework

How to return access token on login with oauth2 in drf?


I want to return the user access token for oauth2 as soon as the user logs in with a login api. Till now I have created a login and register api and I am able to genereate access token via /o/token but I want it as a return value.

Here is my views.py :-

    """
    POST auth/login/
    """
    # This permission class will overide the global permission
    # class setting
    permission_classes = (AllowAny,)
    serializer_class = UserSerializer
    queryset = User.objects.all()

    def post(self, request, *args, **kwargs):
        username = request.data.get("username", "")
        password = request.data.get("password", "")
        user = authenticate(request, username=username, password=password)
        if user is not None:
            # login saves the user’s ID in the session,
            # using Django’s session framework.
            login(request, user)
            return redirect('list-user')

       return Response(status=status.HTTP_401_UNAUTHORIZED)

class RegisterUserView(generics.CreateAPIView):
    """
    POST auth/register/
    """
    permission_classes = (AllowAny,)
    serializer_class = UserRegistrationSerializer

    def post(self, request, *args, **kwargs):
        username = request.data.get("username", "")
        password = request.data.get("password", "")
        email = request.data.get("email", "")
        if not username and not password and not email:
            return Response(
                data={
                    "message": "username, password and email is required to register a user"
                },
                status=status.HTTP_400_BAD_REQUEST
            )
        new_user = User.objects.create_user(
            username=username, password=password, email=email
        )
        return Response(status=status.HTTP_201_CREATED)

and here is my serializers.py

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'password']

class UserRegistrationSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'email','password']

urls.py

    path('admin/', admin.site.urls),
    path('', include('users.urls')),
    path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
]

urls.py for users app

urlpatterns = [
    path('users/', views.UserListView.as_view(), name='list-user'),
    path('auth/login/', views.LoginView.as_view(), name="auth-login"),
    path('auth/register/', views.RegisterUserView.as_view(), name="auth-register")
]

How can I implement it?


Solution

  • You will have to get token from oauth2_provider view for auth token generation and and then you can modify response according to your requirement.

    from oauth2_provider.views.base import TokenView
    
    class CustomAuthView(generics.CreateAPIView):
        permission_classes = (AllowAny,)
        serializer_class = UserSerializer
    
        def post(self, request, *args, **kwargs):
            oauth_response = TokenView.as_view(request, *args, **kwargs)
            if oauth_response.status == 200:
                data = oauth_response.data
                # update data according to your requirement
                return response.Response(data)
            else:
                return oauth_response
    

    If you want to just change url for auth view, then you can do it by adding a new url which will point towards TokenView like this

    from oauth2_provider.views.base import TokenView

    path('auth/login/', TokenView.as_view(), name="auth-login"),
    

    You will have to provide following parameters to your api

    1. grant_type
    2. username
    3. password
    4. client_id
    5. client_secret