def refresh_jwt_token(self, token, override_access_lifespan=None): """ Creates a new token for a user if and only if the old token's access permission is expired but its refresh permission is not yet expired. The new token's refresh expiration moment is the same as the old token's, but the new token's access expiration is refreshed :param: token: The existing jwt token that needs to be replaced with a new, refreshed token :param: override_access_lifespan: Override's the instance's access lifespan to set a custom duration after which the new token's accessability will expire. May not exceed the refresh lifespan """ moment = pendulum.now('UTC') # Note: we disable exp verification because we do custom checks here with InvalidTokenHeader.handle_errors('failed to decode JWT token'): data = jwt.decode( token, self.encode_key, algorithms=self.allowed_algorithms, options={'verify_exp': False}, ) self._validate_jwt_data(data, access_type=AccessType.refresh) user = self.user_class.identify(data['id']) self._check_user(user) if override_access_lifespan is None: access_lifespan = self.access_lifespan else: access_lifespan = override_access_lifespan refresh_expiration = data['rf_exp'] access_expiration = min( (moment + access_lifespan).int_timestamp, refresh_expiration, ) custom_claims = { k: v for (k, v) in data.items() if k not in RESERVED_CLAIMS } payload_parts = dict(iat=moment.int_timestamp, exp=access_expiration, rf_exp=refresh_expiration, jti=data['jti'], id=data['id'], rls=','.join(user.rolenames), **custom_claims) return jwt.encode( payload_parts, self.encode_key, self.encode_algorithm, ).decode('utf-8')
def extract_jwt_token(self, token): """ Extracts a data dictionary from a jwt token """ # Note: we disable exp verification because we will do it ourselves with InvalidTokenHeader.handle_errors('failed to decode JWT token'): data = jwt.decode( token, self.encode_key, algorithms=self.allowed_algorithms, options={'verify_exp': False}, ) self._validate_jwt_data(data, access_type=AccessType.access) return data