Выбор ключа в JWKS с учетом заголовка JWT
Существует ли стандартный способ выбора ключа проверки подписи в хранилище ключей JWKS с учетом заголовка JWS (JWT)?
Моя цель - реализовать библиотеку проверки токенов OpenID Connect ID, и я пытаюсь быть гибким и предвидеть различные конфигурации, но я не уверен, есть ли смысл делать это, если выбор ключа в любом случае специфичен для IdP.
Мой текущий алгоритм обходит JWKS и отфильтровывает:
- Если в JWK есть поле "use", отклоните, если "use" не равно "sig"
- Если в JWK есть поле "key_ops", отклоните, если "key_ops" не содержит "verify"
- Если в JWK есть поле "alg", отклонить, если оно отличается от значения заголовка JWS
- Если заголовок JWS имеет поле "kid", отклонить, если JWK не имеет или имеет другое значение (обратите внимание на обратную логику)
- Если на данном этапе остался ровно один JWK, я использую этот. В противном случае это провал.
Является ли этот подход "достаточно стандартным"?
=== РЕДАКТИРОВАТЬ ===
Я обнаружил, что в разделе 10.1 спецификации ядра OpenID Connect говорится:
При использовании подписей RSA или ECDSA значение параметра alg Header заголовка JOSE ДОЛЖНО быть установлено на соответствующий алгоритм, как определено в JSON Web Algorithms [JWA]. Закрытый ключ, используемый для подписи контента, ДОЛЖЕН быть связан с открытым ключом, используемым для проверки подписи, опубликованным отправителем в его документе набора JWK. Если в указанном документе JWK есть несколько ключей, в заголовке JOSE ДОЛЖНО быть указано дочернее значение. Использование ключей соответствующих ключей ДОЛЖНО поддерживать подпись.
JWK "использование" является обязательным, поэтому я могу смело требовать, чтобы он был "sig".
JWT "ребенок" обязателен, если в JWKS более одного ключа. Это предполагает (хотя и косвенно), что в этом случае JWT "kid" и "JWK" kid должны совпадать. "малыш" не обязательно должен быть уникальным, поэтому вам все еще нужны дополнительные правила.
2 ответа
Это жизнеспособный подход. Я бы сказал, что на этапе 5. у вас может быть несколько действительных ключей одного типа, если нет kid
был переведен в JWS (шаг 4). Вы бы зациклились на этих ключах и передавали их функции проверки по одному, чтобы выяснить, есть ли один, который успешно работает и, таким образом, использовался для подписи сообщения.
Я использую аналогичный подход в своем проекте. Посмотрите на метод selectKey
файла https://github.com/Spomky-Labs/jose/blob/master/src/Object/BaseJWKSet.php
В двух словах, метод sort сортирует ключи в зависимости от аргументов и возвращает первый.