Example #1
0
    def _unpack_header(self, headers):
        """
        Unpacks a jwt token from a request header
        """
        jwt_header = headers.get(self.header_name)
        MissingTokenHeader.require_condition(
            jwt_header is not None,
            "JWT token not found in headers under '{}'",
            self.header_name,
        )

        match = re.match(self.header_type + r'\s*([\w\.-]+)', jwt_header)
        InvalidTokenHeader.require_condition(
            match is not None,
            "JWT header structure is invalid",
        )
        token = match.group(1)
        return token
Example #2
0
    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')
Example #3
0
 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