Search code examples
djangojwtmulti-tenant

Mutliple JWT generation with different django secrets based on subdomains


I am using simple JWT (django-rest-framework-simplejwt). I have an auth server which authenticates users. Each user can belong to a single or multiple Tenants and each tenant is represented by a subdomain. I am trying to generate django secret for each tenant and when the tenant docker launches it uses the django secret generated by the auth server(i store it in .tenant1.local.env for tenant one)

So when a user tries to connect to a domain, system will create auth token using the secret generated for that tenant. Since that tenant will have an access to .tenant.local.env (same secret that was used to generate the token for that tenant) it ll be able authenticate the users using the secret.

The issue is I can not find a simple way to inherit or overwrite a class in django-rest-framework-simplejwt so that I can specify the secret to use to create the token.

There is APISettings(which you specify which secrets to use) in the package but there is no example of how to use it.

IS there a way to specify which secrets to use per access token generation request instead of initializing the whole API for each request.


Solution

  • Any token used for own generation or check backend from .get_token_backend().

    TockenBackend - is container for your settings, and it contain your "api_settings.SIGNING_KEY" too.

    In your case you can override .get_token_backend() in tocken.

    class MyTocken(AccessToken):
        ...
        self get_token_backend(self):
            signing_key = environ("get_security_key_accordingly_tennant")
            tb = super().get_token_backend(self)
            return type(tb)(algorithm=tb.algorithm, signing_key=signing_key,... other init data)
    

    I create every tocken a new TockenBackend instance because i dont know your security flow. But, probably, you can do it only once on server start for every tennant.

    from rest_framework_simplejwt.state import token_backend
    token_backend.signing_key = environ("get_security_key_accordingly_tennant")
    
    class MyTocken(AccessToken):
       _token_backend = token_backend
    

    Don't forget to override token class in settings.SIMPLE_JWT:

    SIMPLE_JWT = {
        ...
        "AUTH_TOKEN_CLASSES": ("myproject.myapp.MyToken",),
        ...
    }
    

    More info here: https://django-rest-framework-simplejwt.readthedocs.io/en/latest/settings.html#auth-token-classes

    and here: https://github.com/jazzband/djangorestframework-simplejwt/blob/master/rest_framework_simplejwt/tokens.py#L222

    p.s. Please be patient - if I didn't understand your question.