JS: REST API (Fastify)
Теория: Аутентификация
В обычных веб-приложениях, работающих в браузере, аутентификация обычно осуществляется с помощью cookies, в которых хранится сессионный ключ. Браузер автоматически отправляет эти cookies при загрузке страниц, поддерживая состояние аутентификации пользователя на разных страницах сайта. Однако в API, особенно RESTful API, такие механизмы отсутствуют, поэтому аутентификация там работает немного иначе. В этом уроке мы подробно рассмотрим, как реализовать аутентификацию с помощью API-ключей и JWT-токенов — двух распространенных методов для обеспечения безопасности API.
Аутентификация в веб-приложениях
Прежде чем перейти к аутентификации в API, кратко напомним, как работает аутентификация в традиционных веб-приложениях. Когда пользователь входит в систему, сервер создает сессию и отправляет идентификатор сессии обратно в браузер, обычно храня его в cookie. При последующих запросах браузер отправляет этот cookie обратно серверу, позволяя серверу распознать пользователя и получить данные его сессии.
Этот механизм опирается на автоматическую обработку cookies браузером и способность сервера поддерживать состояние сессии. Хотя это хорошо работает для веб-приложений, это не переносится напрямую на API, особенно когда клиентами являются не браузеры, а другие сервисы или мобильные приложения.
Api Keys
Этот метод аутентификации в API предполагает, что каждое приложение или клиент получает уникальный ключ, который используется для доступа к API. API-ключ обычно выдается разработчику при регистрации приложения в сервисе, предоставляющем API.

API-ключ — это уникальный идентификатор, назначаемый клиенту, который позволяет серверу распознать клиента, делающего запрос. Клиент включает API-ключ в каждый запрос к API, обычно через заголовок или как параметр запроса. Сервер затем валидирует API-ключ, сверяя его со своими записями, чтобы аутентифицировать клиента.
Процесс аутентификации с API-ключами
- Запрос доступа клиентом: Клиент запрашивает API-ключ у поставщика сервиса.
- Выдача API-ключа сервисом: Сервис генерирует уникальный API-ключ и предоставляет его клиенту.
- Запросы клиента к API: Клиент включает API-ключ в каждый запрос к API. Обычно в виде заголовка. У такого заголовка нет стандартного имени и каждый сервис придумывает что-то свое, например,
X-API-KEY. - Валидация API-ключа сервером: Сервер проверяет API-ключ, сверяя его со своими записями для аутентификации клиента.
- Ответ сервера: Если API-ключ валиден, сервер обрабатывает запрос и отправляет ответ.
Пример того, как может выглядеть API-запрос с API-ключом в заголовке:
Многие сервисы позволяют генерировать несколько API-ключей для разных целей, повышая безопасность путем ограничения области действия каждого ключа. Например, вы можете иметь отдельные ключи для разработки, тестирования и продакшн-среды. Продвинутые системы позволяют связывать ключи с определенными правами доступа, контролируя доступ к разным частям API.
На практике API-ключ должен храниться в секрете, как пароль. Если кто-то получит доступ к вашему API-ключу, он сможет делать запросы к API от вашего имени.
Какие проблемы не решают API-ключи
- Проблемы масштабируемости: Серверу необходимо обращаться к базе данных для проверки API-ключа при каждом запросе, что может стать узким местом в системах с высокой нагрузкой или в микросервисной архитектуре.
- Отсутствие контекста пользователя: API-ключи обычно идентифицируют приложение, а не пользователя, что затрудняет выполнение действий от имени конкретных пользователей, если это подразумевается в системе.
- Ограниченная безопасность: API-ключи не предоставляют детального контроля доступа или аутентификации на уровне пользователя.
- Сложность управления: Ротация API-ключей и управление их истечением требует дополнительного администрирования.
Из-за этих ограничений, особенно в системах, требующих аутентификации конкретных пользователей или распределенных архитектур, JWT-токены часто являются лучшим выбором.
JWT Token
JWT (JSON Web Token) — это компактный и URL-безопасный способ передачи информации между сторонами в виде JSON-объекта. Они предназначены для передачи информации безопасно и целостно, поскольку могут быть подписаны или зашифрованы.
Структура JWT
JWT-токен состоит из трех частей, разделенных точками:
- Header (заголовок): содержит метаданные о типе токена и алгоритме подписи.
- Payload (полезная нагрузка): содержит утверждения (claims) или данные, которые вы хотите передать.
- Signature (подпись): используется для проверки целостности токена.
Как работают JWT-токены
JWT-токены позволяют встраивать информацию о пользователе непосредственно в сам токен. Это означает, что серверу не нужно запрашивать базу данных для получения информации о пользователе при каждом запросе, так как он может извлечь данные из токена.
Для получения jwt-токена, клиент должен выполнить аутентификацию через специальный эндпоинт, который вернет токен. Затем, при выполнении запросов к защищенным маршрутам клиент должен включать JWT-токен в каждый запрос. Обычно это делается через заголовок Authorization с использованием схемы Bearer:
Когда токен истекает, клиент должен получить новый токен, обычно повторно аутентифицируясь или используя механизм обновления токена.
Преимущества JWT-токенов
JWT-токен это строка, внешне похожая на API-ключ, но в отличие от ключа, в нее зашифрована полезная информация, например, идентификатор клиента и набор допустимых действий в системе. Благодаря этому JWT позволяет избежать необходимости хранить сессии на сервере и обеспечивает гибкость в распределенных системах, где API могут быть вызваны из различных источников.
- Безсессионность: Нет необходимости хранить данные сессии на сервере.
- Масштабируемость: Сокращает обращения к базе данных, улучшая производительность в распределенных системах.
- Гибкость: Можно включать различные утверждения и устанавливать истечение срока действия токена.
Использование JWT-токенов в Fastify
Работа с JWT-токенами в Fastify автоматизирована благодаря наличию готовой интеграции. Поэтому нам не придется вникать во все тонкости связанные с созданием, расшифровкой и передачей токенов по HTTP. Вы всегда сможете это сделать при желании, а здесь мы сосредоточимся на том, как все подключить и настроить для работы. Начнем с установки пакета:
Далее зарегистрируем плагин и настроим его в вашем приложении. Создайте файл plugins/jwt.js:
Во время настройки создается метод-декоратор authenticate(), который валидирует и расшифровывает jwt-токен. Этот метод автоматически выполняет аутентификацию и извлекает данные из токена помещая их в объект запроса.
Если нам нужна только аутентификация, то достаточно передать этот метод в хук onRequest
Если нужны данные, то после аутентификации они доступны в request.user
И последнее, для работы с jwt-токенами понадобится эндпоинт выдачи токенов. Обычно это происходит после успешной авторизации. В примере ниже для этого создается адрес /tokens внутри которого проверяется пользователь, запросивший токен. Затем формируется сам токен с помощью метода fastify.jwt.sign в который передается объект с данными для шифрования. Именно эти данные, потом оказываются внутри request.user.
Пример того, как это работает:
Вопросы безопасности
- Управление секретом: Секретный ключ для подписания токенов должен храниться в безопасности. Не хардкодьте его; используйте переменные окружения.
- Хранение токена: Клиенты должны безопасно хранить токены, особенно в браузерных приложениях, где токены могут быть уязвимы для XSS-атак.
- HTTPS: Всегда используйте HTTPS для предотвращения перехвата токена через атаки типа "человек посередине".
Сравнение API-ключей и JWT-токенов
Когда использовать каждый метод
- API-ключи: Подходят для простых приложений, где нужно идентифицировать клиента, но не отдельных пользователей, или когда API потребляется серверными приложениями.
- JWT-токены: Идеальны, когда требуется аутентификация на уровне пользователя, безсессионность и масштабируемость, например, в микросервисной архитектуре или при разработке API для мобильных приложений.
Рекомендуемые программы
Завершено
0 / 15
