I just want to mention about my problem. I have already researched many documents but I could not find any solution.
I just try to use django-tenants. Everything seems OK. But If any user gets the token after login, that token works for all tenants.
It's a big leak of security.
I have been thinking about an idea SIGNING_KEY. If I can change SIGNING_KEY for each tenant, it may be fixed. But It did not.
class TenantJWTAuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
tenant = Client.objects.get(schema_name=connection.schema_name)
jwt_secret_key = tenant.jwt_secret_key
settings.SIMPLE_JWT['SIGNING_KEY'] = jwt_secret_key
This is my Middleware to change SIGNING_KEY for each tenant.
class Client(TenantMixin):
name = models.CharField(max_length=100)
paid_until = models.DateField()
on_trial = models.BooleanField()
created_on = models.DateField(auto_now_add=True)
jwt_secret_key = models.CharField(max_length=100, null=True, blank=True)
# default true, schema will be automatically created and synced when it is saved
auto_create_schema = True
class Domain(DomainMixin):
pass
This is my model.
So, I added jwt_secret_key
into my model and I got this field in Middleware and tried to set SIGNING_KEY for jwt. But still, jwt after user login can be used for all tenants.
Does anyone have any idea about my problem? Any suggestion or amendment to my solution?
Thanks.
You can pass schema data to a jwt token based on the db connection by creating a custom serializer inheriting from djangorestframework-simplejwt's
TokenObtainPairSerializer
and passing additional data inget_token
function. You can then use this serializer in a custom view inheriting fromTokenObtainPairView
.Then use this view to obtain the token
To validate this token you have to create a custom authentication class for django rest framework and compare the access token
tenant_schema
to the current connection schema (from another tenant) and if schemas are different don't return the authentication data.Then change your
DEFAULT_AUTHENTICATION_CLASSES
in the project's settingsI think you can achieve something similar with a
jwt_secret_key
field as you can get a tenant object just like you did in your middleware with aconnection.schema_name
and add any tenant data into a token. However, I think a schema name should be enough and there's no need to add additional fields to the tenant model for jwt tokens.