Защита ресурсов API для взаимодействия между машинами
Узнайте, как использовать OAuth 2.0 и JWT для защиты ваших ресурсов API для взаимодействия между машинами.
При создании проекта, который включает несколько сервисов, безопасность ресурсов API является критически важной задачей. В этой статье я покажу вам, как использовать OAuth 2.0 и JWT для защиты связи между сервисами (машина-к-машине), и как применять контроль доступа на основе ролей (RBAC), чтобы следовать принципу минимальных привилегий.
Начнем
Чтобы следовать, я предполагаю, что у вас есть следующие предварительные условия:
- Аккаунт в Logto Cloud или самостоятеленая инстанция Logto
- Как минимум два сервиса, которые должны взаимодействовать друг с другом
Для демонстрации давайте предположим, что у нас есть следующие сервисы:
- Сервис корзины покупок, который предоставляет API для управления корзинами
- Endpoint:
https://cart.example.com/api
- Endpoint:
- Сервис платежей, который предоставляет API для обработки платежей
- Endpoint:
https://payment.example.com/api
- Endpoint:
Про цесс аутентификации
Теперь наш сервис корзины должен вызвать сервис платежей для обработки платежей. Процесс аутентификации следующий:
Некоторые ключевые понятия на диаграмме выше:
- JWT (RFC 7519): JSON Web Token. См. нашу предыдущую статью для введения в JWT.
- JWK (RFC 7517): JSON Web Key, который используется для проверки подписи JWT. Набор JWK - это набор JWKов.
- Грант "client_credentials" (RFC 6749): тип гранта в OAuth 2.0. Он использует учетные данные клиента для получения токена доступа. Мы продемонстрируем детали в следующих разделах.
Каждый участник на диаграмме выше играет свою роль в процессе аутентификации:
- Сервис корзины: клиент, которому нужно вызвать сервис платежей. Хотя это и сервис, он является клиентом в контексте OAuth 2.0, и такие клиенты мы называем "machine-to-machine applications" в Logto.
- Logto: сервер авторизации OAuth 2.0, который выдает токены доступа.
- Сервис платежей: ресурс API, который предоставляет API для обработки платежей.
Давайте пройдемся по процессу аутентификации шаг за шагом.
Первоначальная настройка
Чтобы выполнить процесс аутентификации, нам нужно создать приложение "machine-to-machine" (сервис корзины) и ресурс API (сервис платежей) в Logto.
Создание ресурса API
Поскольку наш сервис корзины должен знать о API сервиса платежей при выполнении аутентификации, сначала нужно создать ресурс API. Перейдите в Консоль Logto, нажмите API ресурсы в левом боковом меню и нажмите Создать ресурс API. В открывшемся диалоге мы предлагаем несколько руководств, чтобы помочь вам начать. Вы также можете нажать Продолжить без руководства, чтобы пропустить его.
Введите имя и идентификатор API, например, Сервис платежей
и https://payment.example.com/api
, затем нажмите Создать ресурс API.
После создания ресурса API вы будете перенаправлены на страницу с деталями. Мы можем оставить ее как есть на данный момент.
Создание приложения "machine-to-machine"
Нажмите Приложения в левом боковом меню и нажмите Создать приложение. В открывшемся диалоге найдите карточку Machine-to-machine и нажмите Начать создание.
Введите имя приложения, например, Сервис корзины
, и нажмите Создать приложение. Будет показано интерактивное руководство, которое поможет вам настроить приложение. Вы можете следовать руководству, чтобы понять основные принципы использования, или нажать Готово и закончить, чтобы пропустить его.
Запрос токена доступа
Поскольку приложения "machine-to-machine" предполагаются защищенными (например, они развернуты в частной сети), мы можем использовать грант OAuth 2.0 "client_credentials" для получения токена доступа. Он используе т основную аутентификацию для аутентификации клиента:
- URL запроса - это конечная точка токена вашего экземпляра Logto. Вы можете найти и скопировать его на вкладке Дополнительные настройки на странице с деталями приложения "machine-to-machine".
- Метод запроса -
POST
. - Заголовок запроса
Content-Type
-application/x-www-form-urlencoded
. - Для заголовка
Authorization
значение -Basic <base64(app_id:app_secret)>
, гдеapp_id
иapp_secret
- это ID и секрет приложения "machine-to-machine" соответственно. Вы найдете их на странице с деталями приложения. - Тело запроса должно указывать тип гранта и идентификатор API. Например,
grant_type=client_credentials&resource=https://payment.example.com/api
.grant_type=client_credentials
: фиксированное значение для гранта "client_credentials".resource=https://payment.example.com/api
: идентификатор API ресурса, к которому хочет получить доступ клиент.- Если приложению нужно получить разрешения с помощью областей (scopes), вы также можете указать области в теле запроса. Например,
scope=read:payment write:payment
. Мы обсудим области позже.
Вот пример запроса с использованием curl
:
Успешный ответ будет выглядеть так:
Отправка запроса с заголовком авторизации
Теперь у нас есть токен доступа, и мы можем добавить его в заголовок Authorization
запроса к ресурсу API. Например, если мы хотим вызвать API POST /payments
службы платежей, мы можем отправить следующий запрос:
Проверка JWT
Вы можете заметить, что служба платежей должна проверять JWT с использованием набора JWK и может иметь локальный кэш набора JWK, чтобы избегать получения набора JWK с Logto каждый раз. К счастью, благодаря популярности JWT, существует множество библиотек, которые могут помочь вам достичь цели с помощью нескольких строк кода.
Эти библиотеки обычно называются "jose" (JavaScript Object Signing and Encryption) и ли "jsonwebtoken". Например, в Node.js мы можем использовать jose для проверки JWT:
Если проверка успешна, переменная payload
будет декодированным полезным нагрузком JWT. В противном случае будет выброшена ошибка.
Применение контроля доступа на основе ролей
Теперь мы успешно защитили связь между сервисом корзины и сервисом платежей. Тем не менее, процесс аутентификации только гарантирует, что клиент - это настоящий сервис корзины, но не гарантирует, что сервис корзины имеет какие-либо разрешения для выполнения действий на сервисе платежей.
Предположим, что мы хотим разрешить сервису корзины создавать платежи, но не читать платежи.
Определение разрешений
В Logto "scopes" и "permissions" взаимозаменяемы. Перейдите на страницу с деталями ресурса API службы платежей и перейдите на вкладку Разрешения. Она должна быть пустой. Нажмите Создать разрешение, введите read:payment
в качестве имени разрешения и введите Чтение платежей
в качестве описания разрешения. Затем нажмите Создать разрешение.
Повторите вышеуказанные шаги, чтобы создать другое разрешение с именем write:payment
и описанием Создание платежей
.
Создание роли для "machine-to-machine"
Роль - это группа разрешений. В Logto приложения "machine-to-machine" могут быть назначены роли для предоставления разрешений. Нажмите "Роли" в левом боковом меню и нажмите Создать роль.
- Введите
checkout
в качестве имени роли и введитеСлужба оформления заказа
в качестве описания роли. - Нажмите Показать больше параметров. Выберите "Роль приложения machine-to-machine" в качестве типа роли.
- В разделе "Назначенные разрешения" нажмите на стрелку слева от названия ресурса API (Служба платежей) и выберите разрешение
write:payment
. - Нажмите Создать роль.
- Поскольку у нас уже есть приложение "machine-to-machine" (Сервис корзины), мы можем непосредственно назначить ему роль на следующем шаге. Установите флажок слева от имени приложения (Сервис корзины) и нажмите Назначить приложения.
Запрос токена доступа с областями
В дополнение к параметрам тела запроса, о которых мы говорили в Запрос токена доступа, мы также можем указать области в теле запроса. Например, если мы хотим запросить разрешение write:payment
, мы можем отправить следующий запрос:
Чтобы запросить несколько областей, вы можете разделить их пробелами. Например, scope=write:payment read:payment
.
Проверка областей
Если действие требует разрешения write:payment
в службе платежей, мы можем проверить области, утверждая, что утверждение scope
полезной нагрузки JWT:
Заключение
Если вы хотите защитить доступ к сервису корзины, вы также можете применить тот же процесс аутентификации. На этот раз сервис корзины является ресурсом API, а клиент - это другой сервис, которому нужно получить доступ.
С Logto ваши API ресурсы защищены с помощью OAuth 2.0 и JWT, и вы можете следовать принципу минимальных привилегий, применяя контроль доступа на основе ролей. Кроме того, вы можете использовать Logto для управления вашими пользователями и их разрешениями, и даже интегриро ваться с поставщиками идентификации третьих сторон.