Skip to content
This repository has been archived by the owner on May 26, 2020. It is now read-only.

how to refresh existing tokens??? #474

Open
cysnet opened this issue Apr 9, 2019 · 6 comments
Open

how to refresh existing tokens??? #474

cysnet opened this issue Apr 9, 2019 · 6 comments

Comments

@cysnet
Copy link

cysnet commented Apr 9, 2019

image

i got an error message orig_iat field is required.

the settings is :
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ), }

@cysnet
Copy link
Author

cysnet commented Apr 9, 2019

it is worked!!!! thanks a lot

@SamsadSajid
Copy link

How did you do it?

@wnz27
Copy link

wnz27 commented May 21, 2019

@SamsadSajid
first,the orig_iag is the token created time,this issue means the token we send to server don't have this parameter.
then we look the refresh source code, in rest_framework_jwt.serializers.py:

class RefreshJSONWebTokenSerializer(VerificationBaseSerializer):
    def validate(self, attrs):
        token = attrs['token']
        payload = self._check_payload(token=token)
       user = self._check_user(payload=payload)
       # Get and check 'orig_iat'
       orig_iat = payload.get('orig_iat')

       if orig_iat:
           # Verify expiration
           refresh_limit = api_settings.JWT_REFRESH_EXPIRATION_DELTA

           if isinstance(refresh_limit, timedelta):
               refresh_limit = (refresh_limit.days * 24 * 3600 +
                                refresh_limit.seconds)

           expiration_timestamp = orig_iat + int(refresh_limit)
           now_timestamp = timegm(datetime.utcnow().utctimetuple())

           if now_timestamp > expiration_timestamp:
               msg = _('Refresh has expired.')
               raise serializers.ValidationError(msg)
       else:
           msg = _('orig_iat field is required.')
           raise serializers.ValidationError(msg)

       new_payload = jwt_payload_handler(user)
       new_payload['orig_iat'] = orig_iat

       return {
           'token': jwt_encode_handler(new_payload),
           'user': user
       }

that's very clear :

     if orig_iag:
           xxxxxxxxxxxxxxx  
     else:
            msg = _('orig_iat field is required.')
            raise serializers.ValidationError(msg)

so, we should fix it?
because we through this method jwt_payload_handler to generate the jwt-token,
we must look the source code:

def jwt_payload_handler(user):
    username_field = get_username_field()
    username = get_username(user)

    warnings.warn(
        'The following fields will be removed in the future: '
        '`email` and `user_id`. ',
        DeprecationWarning
    )

    payload = {
        'user_id': user.pk,
        'username': username,
        'exp': datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA
    }
    if hasattr(user, 'email'):
        payload['email'] = user.email
    if isinstance(user.pk, uuid.UUID):
        payload['user_id'] = str(user.pk)

    payload[username_field] = username

    # Include original issued at time for a brand new token,
    # to allow token refresh
    if api_settings.JWT_ALLOW_REFRESH:
        payload['orig_iat'] = timegm(
            datetime.utcnow().utctimetuple()
        )

    if api_settings.JWT_AUDIENCE is not None:
        payload['aud'] = api_settings.JWT_AUDIENCE

    if api_settings.JWT_ISSUER is not None:
        payload['iss'] = api_settings.JWT_ISSUER

    return payload

this if api_settings.JWT_ALLOW_REFRESH:
it means if JWT_ALLOW_REFRESH exist then the handler to set the orig_iag,
and the JWT_ALLOW_REFRESH default is False, so we add it to the our settings file and set it to True

ps:
on the basis of RefreshJSONWebTokenSerializer, we can know
the JWT_REFRESH_EXPIRATION_DELTA's value means in this time field you can refreash!

hope useful to you

@seon54
Copy link

seon54 commented May 22, 2019

I've tested and found out that even though there is 'JWT_REFRESH_EXPIRATION_DELTA' on settins.py, it doesn't work. Only 'JWT_EXPIRATION_DELTA' works for refresh token.

@wnz27
Copy link

wnz27 commented May 22, 2019

I've tested and found out that even though there is 'JWT_REFRESH_EXPIRATION_DELTA' on settins.py, it doesn't work. Only 'JWT_EXPIRATION_DELTA' works for refresh token.

@seon54

Like I said above,the JWT_REFRESH_EXPIRATION_DELTA's value means in this time field you can refreash!
so you should set JWT_REFRESH_EXPIRATION_DELTA bigger than JWT_EXPIRATION_DELTA.

so base i understand, because i haven't research all django-jwt source code. so i think two situation:

when your jwt token expired:
1、the operation of refresh need you take a intiative to call.
2、the operation of refresh autocall

but i browse the django-jwt source code ,I don't seem find autocall about refresh.
hope useful to u!

@Matt-Texier
Copy link

Hi Guys,

Just a comment and observation on my side about the same issue : for me, as soon as you set JWT_VERIFY_EXPIRATION to true, the decoder of the JWT is checking expiration of the token.

As such, even when running token refresh, the same decoding method is called and the program exits at this line of code :
payload = self._check_payload(token=token)

If you look at this line of code:
https://github.com/GetBlimp/django-rest-framework-jwt/blob/0a0bd402ec21fd6b9a5f715d114411836fbb2923/rest_framework_jwt/utils.py#L101

You see that expiration is always tested during decoding once set in settings of Django. Even when asking for a refresh ...

For me, in case of refresh it should not check expiration time of the token but rather check JWT_REFRESH_EXPIRATION_DELTA.

So I wonder if we are not facing a bug here ... but I am not 100% sure.

What do you think ?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants