Djangorestframework-simplejwt: How to access request object in get_token?

Created on 26 Jul 2019  路  9Comments  路  Source: jazzband/djangorestframework-simplejwt

I want to access request object in get_token because I want to get company_id from the POST request and add into token claims.

class MyTokenObtainPairSerializer(TokenObtainPairSerializer):

    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)

        # Add custom claims
        token['company_id'] = request.POST['company_id']

        return token

All 9 comments

I have this problem too.
Anyone have a solution?

Hi amir,

Nope still searching for the answer.

Are you sure you want to do be doing that? Without knowing any more about what you're trying to do, it's a huge security risk to allow users to provide the information (via POST data) that you then sign with your service's signing key.

Since the rest_framework_simplejwt.serializers.TokenObtainPairViewSerializer inherits from the Django Rest Framework Serializer class, I think this stackoverflow question can get us there.

From the stackoverflow link, you can see that the request is stored on the context property of the serializer. I'm brand new to the @classmethod decorator, so hopefully someone with more experience can step in and say if this is appropriate. If you skip the decorator, the self keyword will contain the request context.

class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    def get_token(self, user):
        token = super().get_token(user)
        token['other_thing'] = self.context['request'].data['other_thing']
        return token

One you create a view and a URL, post requests should generate token claims that include other_thing.

Here's what my post request contains:

{"username": "hello", "password": "world", "other_thing": "hello, world"}

When I decode this token in a StackBlitz, it contains the other_thing.

I have no idea if this implementation will affect other parts of your app. If you give it a try, let us know how it goes.

@vitale232 I would strongly recommend against doing that! You should really only be putting curated data into tokens. Don't just take whatever a third party gives you in POST data and stick it in a token. That's a great way to introduce vulnerabilities into your app. Remember that, by signing a bearer token, you're basically saying to anything that accepts it as proof of authorization (or authentication) that the information contained there within has been verified and is safe to use to make decisions about what the bearer is allowed access to. If you stick any value in a token, you should first validate it somehow and ensure that no third party was able to tamper with it arbitrarily.

@davesque Thanks, that makes sense to me. I personally don't see the use case for this... I would probably just submit two requests from the client. One for the token, one for the other_thing.

Is this one of the reason you use the @classmethod decorator in the docs?

I suppose I chose the classmethod decorator just because the method didn't need access to the serializer instance at the time I wrote it. So I thought I'd make that clear to the reader of the code with that decorator.

And there may still be a use-case for adding extra data to tokens. It's just that you need to be careful about where it comes from and make sure it's undergone some kind of verification process. For example, the user id is safe to insert into a token because it is determined by verifying the credentials submitted with an authentication request. (Actually, some might argue that sending an auto-incrementing database id into the wild also isn't safe. But that's kind of a different discussion.)

Thank you for your comment
but i want generate a token via agent that for example if a user use from another browser, become invalid token.
what is your opinion?

I personally don't see the use case for this... I would probably just submit two requests from the client. One for the token, one for the other_thing.

After huge discussion we've decided to go with two API to our backend.

  1. For getting the token by submitting the username, password. This API also return company information if the user assign to single company. else
  2. Using the token to fetch all the company_ids and anytime the client will have multiple companies associated with it can able to switch without relogin.

@davesque Our internal team want to attach company_id in token. They arguing like anyway if one can obtain the token then they can also view the user_id so showing the company_id will not make any difference.

And also in future we are planning to send additional data over headers so finally we decided to send company_id in Headers.

Thanks for the awesome framework.

Was this page helpful?
0 / 5 - 0 ratings