Search code examples
djangoauthenticationpermissionsaccess-tokendjango-rest-framework-simplejwt

Using Django, SimpleJWT checking User permission to show content belongs to his own company


I am using React(front), Django(server-side), Simple JWT for User Auth Model and Postgres DB.

Let me explain my model: Company owns many properties, and each company has multiple users. As a user logs in, I want them to see a list of properties that belongs to their own company. As the user selects any property from the list, I need to again check if the user has permission and then run the queries. I am currently using Simple JWT for authentication. As the user logs in, the backend generates Access and Refresh tokens. With every request sent from the user side, I am sending JWT access token. On the server side, I want to decode the token, look at what company user belongs to, filter queries accordingly and send the JsonResponse.

Here is my Company Model:

class Company(models.Model):
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='company_user', on_delete=models.CASCADE, null=True)
    company_name = models.CharField(max_length=200, null=True)
    slug = models.SlugField(max_length=200, unique=True)   

    class Meta:
        ordering = ['name']

    def __str__(self):
        return self.name

Here is the property model:

class Property(models.Model):
    company = models.ForeignKey(Company, related_name='prop_company', null = True, on_delete=models.CASCADE)
    property_name = models.CharField(max_length=200, null=True)
    property_type = models.CharField(max_length=200, null=True)
   

    def __str__(self):
        return self.property_name 

Here is the property data

class PropertyData(models.Model):
    
    data = models.ForeignKey(Property, related_name='property_data', null = True, on_delete=models.CASCADE)
    lat = model.FloatField(null=True)
    long = model.FloatField(null=True)

How should I handle the JWT token in the backend and check which company user belongs to, run queries accordingly and then send a success message along with the filtered data?


Solution

  • In simple-JWT you can customize your token claim. For this add this in your serializer.py file.

    from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
    from rest_framework_simplejwt.views import TokenObtainPairView
    
    class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
        @classmethod
        def get_token(cls, user):
            token = super().get_token(user)
    
            # Add custom claims
            token['company_name'] = user.company_user.company_name # will add requested user company name in token
            # ...
    
            return token
    
    # your views.py
    class CustomTokenObtainPairView(TokenObtainPairView):
        serializer_class = CustomTokenObtainPairSerializer
    

    and also don't forget to update your urls.py file.

    from .views import CustomTokenObtainPairView
    
    
    urlpatterns = [
        ...
        path('api/token/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'),
        ...
    ]
    

    Hope this will solve your problem :)