#authentication #jwt #microservices
#аутентификация #jwt #микросервисы
Вопрос:
Я создал Rest API на основе PHP Slim framework, который использует веб-токены JSON (JWT) для аутентификации и авторизации доступа.
Чтобы использовать API, клиент должен сначала аутентифицироваться, отправив свои учетные данные по специальному /auth/token
маршруту, который, если он правильный, возвращает токен с цифровой подписью, содержащий список разрешенных разрешений. Все последующие запросы к API требуют токен для аутентификации и авторизации. Это довольно стандартный материал и работает хорошо.
Но теперь я хочу отделить /auth/token
сервис от его собственного микросервиса, чтобы в будущем я мог повторно использовать его с другими API.
Проблема в том, как теперь API будут аутентифицировать JWT, поскольку у них нет доступа к секрету, который использовался для его создания?
Я использую FirebaseJWTJWT
для генерации токена, который будет перемещен в новую службу аутентификации. И я использую tuupola/slim-jwt-auth
промежуточное программное обеспечение для аутентификации полученного токена в каждом API.
Поскольку каждый API и новая служба аутентификации будут запущены на одном хосте, я мог бы, возможно, поделиться секретом между ними всеми, но это похоже на плохую практику. Есть ли способ лучше?
Ответ №1:
Лучше подписывать JWT с использованием закрытого / открытого ключа (алгоритм RSA или ECDSA) вместо секретного (алгоритм HMAC). В этом случае ваша служба аутентификации будет подписывать JWT закрытым ключом, а другие API будут проверять JWT открытым ключом, ну… тогда вам все равно нужно будет распространять открытый ключ в ваших API, но у вас есть варианты.
Зависит от вашей архитектуры, вы можете посмотреть на:
Шаблон шлюза API
Для микросервисной архитектуры хорошей практикой является использование шаблона API Gateway. Подробнее о шаблоне шлюза. API Gateway может проверять токен JWT, а затем прокси-запросы к вашим сервисам. Таким образом, служба аутентификации будет подписывать токен JWT закрытым ключом, тогда запросы к API будут проходить через API Gateway. API Gateway будет проверять токен с помощью открытого ключа, поэтому вы не будете распространять открытый ключ на все API за прокси.
При таком подходе вам понадобится шлюз API, вы можете посмотреть: express-gateway, kong jwt plugin, tyk и т.д. Также от шлюза API гораздо больше преимуществ, чем просто проверка токена JWT, таких как управление трафиком, аналитика, ведение журнала, преобразования запросов и ответов и так далее.
Управление секретами
Вместо API Gateway или в дополнение к нему вы можете взглянуть на централизованные системы управления секретами, такие как Hashi Vault. В зависимости от размера проекта / команды это может быть излишеством для вашего проекта.
Ответ №2:
Криптографические алгоритмы, которые могут быть использованы для генерации кода аутентификации сообщения (MAC) или цифровой подписи, перечислены в RFC 7518.
Из всего списка алгоритмов единственным, который «требуется» для реализации совместимой реализацией, является HMAC с использованием SHA256 (HS256). HS256 требует личного секрета для подписи токена, а также для проверки токена. Если вы используете HS256, в идеале вы не должны делиться секретом между всеми серверами. Вместо этого логика подписи и проверки tge останутся на «сервере авторизации» (терминология OAuth2). Отдельные «серверы ресурсов» (опять же терминология OAuth2) будут вызывать службу на сервере авторизации для проверки токена. Однако может оказаться непрактичным вызывать API проверки токена сервера авторизации для каждого вызова api. Поэтому, возможно, для серверов ресурсов было бы хорошей идеей кэшировать JWT и просто сравнивать JWT во входящих запросах с кэшированным списком JWT. Если входящий JWT отсутствует в кэше, только тогда будет вызвана функция проверки подлинности сервера авторизации. Это гарантирует, что секретный ключ подписи не нужно использовать совместно, и функция проверки удаленным сервером авторизации также не вызывается для каждого вызова api.
Двумя другими рекомендуемыми алгоритмами в RFC являются «RSASSA-PKCS1-v1_5 с использованием SHA-256» и «ECDSA с использованием P-256 и SHA-256» (ES256), где более поздний (ECDSA), вероятно, также будет сделан «обязательным» в будущем.
Если вы используете ES256, вы должны хранить закрытый ключ на сервере авторизации для подписи токенов и совместно использовать открытый ключ tge на всех серверах ресурсов, чтобы каждый сервер ресурсов мог проверять подпись с использованием открытого ключа. Это определенно избавляет серверы ресурсов от необходимости вызывать сервер авторизации для проверки за счет увеличения объема вычислений и без необходимости делиться секретом с каждым сервером ресурсов.
Комментарии:
1. Мне очень нравится идея заставить «Сервер авторизации» создавать и проверять токен, если я не могу использовать открытые / закрытые ключи (
tuupola/slim-jwt-auth
похоже, это не поддерживается). Я должен быть в состоянии создать уровень промежуточного программного обеспечения для применения проверки к каждому маршруту.