如果用户来自受信任的IP地址,则允许JWT令牌过期

如果用户来自受信任的IP地址,则允许JWT令牌过期,ip,whitelist,flask-jwt-extended,Ip,Whitelist,Flask Jwt Extended,使用flask jwt extended,我遇到了这样一种情况:API必须同时服务于两个用户,还必须服务于一系列web应用程序,例如,后者中的一个是聊天机器人 对于用户来说,开箱即用的软件包功能非常完美,但是对于web应用程序,我希望JWT令牌的行为更像API键,它们不一定会在一段时间后过期 因此,我想做的是,如果请求来自预定义的可信IP地址,则禁止检查“到期日” 我有一个sqlalchemy模型,它存储可信的“ip地址”,这与用户模型有外键关系,这意味着用户可以指定一个或多个白名单上的ip地址

使用flask jwt extended,我遇到了这样一种情况:API必须同时服务于两个用户,还必须服务于一系列web应用程序,例如,后者中的一个是聊天机器人

对于用户来说,开箱即用的软件包功能非常完美,但是对于web应用程序,我希望JWT令牌的行为更像API键,它们不一定会在一段时间后过期

因此,我想做的是,如果请求来自预定义的可信IP地址,则禁止检查“到期日”

我有一个sqlalchemy模型,它存储可信的“ip地址”,这与用户模型有外键关系,这意味着用户可以指定一个或多个白名单上的ip地址

现在,解码令牌函数:

有一个参数allow_expired,它允许覆盖到期,但是,它在_decode_jwt_from_请求中不以任何方式使用。。。函数,它在验证JWT令牌时似乎很有用

最终,我需要@jwt_的decorator替换,允许使用过期的令牌,前提是请求来自白名单上的IP地址

我的问题有两个:

从安全角度来看,上述结构是否正常, 在不必复制和稍微修改库中的整个函数的情况下,我如何进行上述操作?
除非有人告诉我更好的方法,否则我最终会修补decode_token函数:

我突出显示了“补丁”区域,该区域拦截“ExpiredSignatureError”,并检查ip地址是否在用户ip白名单中,如果是,则允许正常业务

def decode_token(encoded_token, csrf_value=None, allow_expired=False):
    """
    Returns the decoded token (python dict) from an encoded JWT. This does all
    the checks to insure that the decoded token is valid before returning it.

    :param encoded_token: The encoded JWT to decode into a python dict.
    :param csrf_value: Expected CSRF double submit value (optional)
    :param allow_expired: Options to ignore exp claim validation in token
    :return: Dictionary containing contents of the JWT
    """
    jwt_manager = _get_jwt_manager()
    unverified_claims = jwt.decode(
        encoded_token, verify=False, algorithms=config.decode_algorithms
    )
    unverified_headers = jwt.get_unverified_header(encoded_token)
    # Attempt to call callback with both claims and headers, but fallback to just claims
    # for backwards compatibility
    try:
        secret = jwt_manager._decode_key_callback(unverified_claims, unverified_headers)
    except TypeError:
        msg = (
            "The single-argument (unverified_claims) form of decode_key_callback ",
            "is deprecated. Update your code to use the two-argument form ",
            "(unverified_claims, unverified_headers)."
        )
        warn(msg, DeprecationWarning)
        secret = jwt_manager._decode_key_callback(unverified_claims)

    try:
        return decode_jwt(
            encoded_token=encoded_token,
            secret=secret,
            algorithms=config.decode_algorithms,
            identity_claim_key=config.identity_claim_key,
            user_claims_key=config.user_claims_key,
            csrf_value=csrf_value,
            audience=config.audience,
            issuer=config.issuer,
            leeway=config.leeway,
            allow_expired=allow_expired
        )
    except ExpiredSignatureError:
        expired_token = decode_jwt(
            encoded_token=encoded_token,
            secret=secret,
            algorithms=config.decode_algorithms,
            identity_claim_key=config.identity_claim_key,
            user_claims_key=config.user_claims_key,
            csrf_value=csrf_value,
            audience=config.audience,
            issuer=config.issuer,
            leeway=config.leeway,
            allow_expired=True
        )


        # ------------------------------------------------------------
        # Author:   Nicholas E. Hamilton
        # Date:     25th August 2019
        # Patch:    Check if ip address is in the whitelist,
        #           and if so, permit an expired token
        # ------------------------------------------------------------
        user = user_loader(expired_token[config.identity_claim_key])
        ip_address = request.remote_addr
        if user and ip_address:
            ip_whitelist = [x.ip_address for x in user.ip_whitelist]
            if ip_address in ip_whitelist:
                return expired_token
        # >>>> END PATCH

        # Proceed as normal
        ctx_stack.top.expired_jwt = expired_token
        raise

flask_jwt_extended.view_decorators.decode_token = flask_jwt_extended.utils.decode_token = decode_token