2

我正在使用 auth0,我有两个客户端(ios,react)和一个使用go-auth0的 Go 后端 API 。

我按照文档制作了一个如下所示的Verify方法:

func Verify(handle httprouter.Handle) httprouter.Handle {
    return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
        auth0Domain := viper.GetString("auth0.issuer")
        audience := []string{viper.GetString("auth0.audience")}

        client := auth0.NewJWKClient(auth0.JWKClientOptions{URI: auth0Domain + ".well-known/jwks.json"}, nil)
        configuration := auth0.NewConfiguration(client, audience, auth0Domain, jose.RS256)
        validator := auth0.NewValidator(configuration, nil)
        _, err := validator.ValidateRequest(r)
        if err != nil {
            w.Header().Set("Content-Type", "application/json")
            w.WriteHeader(http.StatusUnauthorized)
            json.NewEncoder(w).Encode(map[string]string{"error": "Unauthorized"})
            return
        }

        handle(w, r, p)
    }
}

不幸的是,我注意到第一次验证需要大约 400 毫秒,后续验证需要大约 50 毫秒。

但是,如果我用验证器的字段初始化一个结构,将所有设置代码移动到一个Initialize()中,那么它只需要大约 1 毫秒:

func Verify(handle httprouter.Handle) httprouter.Handle {
    return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {

        _, err := a.validator.ValidateRequest(r)
        if err != nil {
            w.Header().Set("Content-Type", "application/json")
            w.WriteHeader(http.StatusUnauthorized)
            json.NewEncoder(w).Encode(map[string]string{"error": "Unauthorized"})
            return
        }

        handle(w, r, p)
    }
}

这是一个坏主意吗?我今天只是在学习 JWK 并查看 auth0 代码,它们似乎确实构建了一个缓存,但我并不完全理解它是如何工作的。

有人可以让我知道将配置移动到结构中并使用它的验证器是一个好主意吗?

更新

auth0 有一个内置的方法来做到这一点!这是一个例子:

auth0.NewJWKClientWithCache(auth0.JWKClientOptions{URI: a.issuer + ".well-known/jwks.json"}, nil, auth0.NewMemoryKeyCacher(time.Duration(10)*time.Second, 5))

使用此方法,以便为您缓存!:)

4

1 回答 1

2

缓存客户端对象几乎肯定是安全的,而且这样做通常是一个好主意。(“创建一个客户端并重用它”是一个很好的一般规则。)

我的理解是,JWT 的签名密钥通常有效期为几个月,甚至更长。(Auth0 的文档指出,它的 JWKS 文档只有一个密钥,但它会一直发出签名令牌,因此密钥必须在“一段时间”内有效。) RFC 7517没有定义任何与过期相关的参数无论是 JWKS 还是单个 JWK,我认为最好的做法是在 JWKS 端点上使用普通的 HTTP 缓存控件来偶尔刷新它,但不要那么频繁。

于 2018-08-26T11:26:09.930 回答