Это плохая идея для кэширования auth0 JWK

Я использую auth0, и у меня есть два клиента (ios, реагировать) и Go Backend API, использующий go-auth0.

Я проследил за документацией и сделал 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))

Используйте этот метод, чтобы он кешировал для вас!:)

1 ответ

Решение

Почти наверняка должно быть безопасно кэшировать объект клиента, и в целом это обычно является хорошей идеей. ("Создайте одного клиента и используйте его повторно" - это хорошее общее правило.)

Насколько я понимаю, ключи подписи для JWT обычно действительны в течение нескольких месяцев, если не дольше. ( В документации Auth0 отмечается, что в ее документах JWKS всегда есть только один ключ, но он будет выдавать подписанные токены все время, поэтому ключи должны быть действительны в течение некоторого времени.) RFC 7517 не определяет никаких параметров, связанных с истечением времени, для либо JWKS, либо отдельный JWK, и я думаю, что лучше всего использовать обычные элементы управления HTTP-кэшированием на конечной точке JWKS, чтобы периодически обновлять его, но не так часто.

Другие вопросы по тегам