Токены API часто воспринимаются как незначительная деталь реализации: пользователь вошёл, сервер выдал токен, браузер сохранил и отправляет его с каждым запросом |
||
|
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ Атаки на ИИ Внедрение ИИИИ теория Компьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Промпты. Генеративные запросы Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2026-09-12 12:33 Токены API часто воспринимаются как незначительная деталь реализации: пользователь вошёл, сервер выдал токен, браузер сохранил и отправляет его с каждым запросом. На верхнем уровне всё выглядит просто. Но последствия для безопасности далеко не просты. Токен может быть корректно подписан и всё равно украден. Он может использовать сильный криптографический алгоритм, но оставаться активным спустя долгое время после того, как атакующий получил к нему доступ. Он может храниться в удобном месте, доступном для чтения любому внедрённому скрипту. Подпись защищает токен от модификации, но не от кражи. Когда атакующий предъявляет валидный токен доступа, сервер обычно не может отличить легитимного пользователя от злоумышленника: оба отправляют одинаковый токен, оба проходят проверку подписи. Для браузерных приложений безопасность токена определяется не только выбором алгоритма JWT. Она зависит от того, как токен выпущен, где хранится, как передаётся, обновляется, как быстро может быть отозван и можно ли обнаружить подозрительную активность до того, как наступили серьёзные последствия. Рассмотрим полный жизненный цикл токена API — от выпуска до истечения срока или принудительного отзыва. **Выпуск токена: правильный поток OAuth** Модель безопасности закладывается при создании токена. Ошибки на этом этапе сложно исправить потом. Даже сильное хранилище и транспортная безопасность не спасут, если используется неправильный тип разрешений, слишком длинный срок жизни или слабая аутентификация клиента. Выбор потока OAuth зависит от типа клиента. Одностраничные приложения и мобильные приложения — публичные клиенты. Они не могут безопасно хранить постоянный секрет клиента, поскольку их код и среда выполнения контролируются пользователем. Для них стандартом является поток кода авторизации с PKCE (Proof Key for Code Exchange). PKCE привязывает запрос авторизации к временному секрету верификации, который генерирует клиент. Сначала клиент создаёт произвольный верификатор и формирует на его основе challenge, который включается в запрос авторизации. Оригинальный верификатор остаётся на клиенте. Когда приложение обменивает код авторизации на токены, оно должно предоставить оригинальный верификатор. Атакующий, перехвативший только код авторизации, не сможет завершить обмен без совпадения значения верификации. Для коммуникации между машинами требования другие. Сервис бэкенда может использовать client credentials grant, поскольку может хранить секрет в защищённой среде. Такие токены должны быть короткоживущими, а секреты клиента — регулярно ротироваться и храниться в отдельной системе управления секретами, а не в репозитории. Для новых приложений старый явный поток (implicit flow) использовать больше не следует. Он выставляет токены в перенаправлениях и не имеет средств защиты, которые предоставляет поток кода авторизации с PKCE. Современные браузеры имеют лучшие варианты. **Срок жизни токена: баланс между опытом и безопасностью** Срок жизни токена — это всегда компромисс между удобством пользователя и временем раскрытия токена. Более длительный срок уменьшает количество обновлений, но даёт атакующему больше времени для использования украденных данных. Токен доступа для браузерного приложения обычно должен быть короткоживущим — хорошая отправная точка от 5 до 15 минут. Точное значение зависит от чувствительности приложения. Для низкорисковой контентной платформы допустимо более длинное окно сессии. Финансовые панели, внутренние админки и приложения здравоохранения должны использовать короткоживущие токены. Токены обновления служат другой цели: они предназначены только для выдачи новых токенов и обычно живут дольше — от нескольких часов до нескольких дней. Скользящая сессия может улучшить пользовательский опыт, не делая сессию вечной. Например, токен обновления остаётся валидным 7 дней и продлевается при каждом использовании, а отдельный абсолютный лимит гарантирует, что полная сессия не длится дольше 30 дней без повторной аутентификации. Без абсолютного лимита часто используемая сессия может длиться вечно. **Защита конечных точек аутентификации** Конечные точки входа и обновления токенов — это входы в систему аутентификации. Они подвержены перебору паролей, подбору учётных данных, атакам грубой силы, повторного использования и автоматизированному злоупотреблению. Ограничение количества запросов должно применяться на шлюзе API, обратном прокси или уровне приложения. При этом учитывать нужно не только IP-адрес: атакующий может распределить запросы между множеством адресов. Более сильная стратегия сочетает идентификатор аккаунта, информацию об устройстве, диапазон IP, частоту запросов и предыдущие неудачи. Конфиденциальные клиенты могут аутентифицироваться с помощью подписанных утверждений (signed assertions) вместо повторной передачи статичного секрета. Клиентское утверждение — это короткоживущий подписанный JWT с идентификатором клиента, целевой аудиторией, временем выпуска, временем истечения и уникальным идентификатором запроса. Поскольку утверждение быстро истекает и содержит уникальный идентификатор, повтор перехваченного запроса становится сложнее. **Хранение токенов: главная проблема браузеров** Хранение — одна из самых спорных частей браузерной аутентификации. Браузерному приложению нужно где-то хранить сессию пользователя. Самые очевидные механизмы часто используются неправильно. Хранение токена доступа в localStorage удобно: токен переживает перезагрузку страницы, его легко читать и добавлять к запросам из любой части приложения. Но это удобство создаёт главную проблему: каждый скрипт на странице может читать локальное хранилище. Если атакующий выполнит JavaScript через XSS-уязвимость, взломанную зависимость, встроенный скрипт аналитики или вредоносное расширение браузера, токен может быть скопирован и отправлен куда угодно. sessionStorage имеет ту же проблему доступа через JS. Оно очищается при закрытии вкладки, но это не защищает от чтения вредоносными скриптами. Риск не ограничен явными уязвимостями приложения. Атака на цепочку поставок может выполнить вредоносный код из NPM-пакета, стороннего виджета или скрипта с CDN. Внедрённый код работает с теми же привилегиями, что и код приложения. С точки зрения браузера, это просто ещё один скрипт. Часто оправдываются тем, что localStorage — временное решение, которое заменят позже. Но часто замены не происходит: как только аутентификация заработала и приложение вышло в продакшн, менять архитектуру становится дорого. Временный костыль становится постоянной инфраструктурой. Для чувствительных браузерных приложений долгоживущие учётные данные не должны храниться в месте, доступном для чтения через JS. Куки с атрибутом HttpOnly недоступны для чтения скриптами. Каждый атрибут куки даёт свою защиту: Secure обеспечивает передачу только по HTTPS, SameSite ограничивает включение куки в межсайтовые запросы. Префикс __Host- добавляет более строгие требования: куки должен использовать HTTPS, не содержать атрибут Domain и иметь Secure. Это помогает предотвратить установку конфликтующего куки для родительского домена менее доверенным поддоменом. HttpOnly-куки сильно уменьшает риск прямой кражи токена через XSS. Но это не делает XSS-атаки безвредными. Вредоносный скрипт по-прежнему может выполнять аутентифицированные операции внутри скомпрометированной страницы. Он не может прочитать значение куки, но браузер автоматически добавляет куки в запросы. HttpOnly защищает учётные данные от извлечения, но не от всех злоупотреблений сессией. Куки автоматически включаются в совпадающие запросы, что удобно, но создаёт риски подделки межсайтовых запросов (CSRF). Атакующий может попытаться заставить браузер жертвы отправить аутентифицированный запрос с другого сайта. SameSite блокирует многие сценарии CSRF, но приложения не должны полагаться только на этот флаг для чувствительных операций. Запросы, модифицирующие состояние, могут требовать отдельный токен CSRF: сервер сравнивает отправленное значение с доверенным значением, связанным с сессией. Другой вариант — шаблон двойной отправки куки, хотя привязанный к серверу токен обычно проще, когда приложение уже поддерживает состояние сессии. Валидация HTTP-заголовков Origin и Referer может дать дополнительный слой защиты. Чувствительные запросы стоит защищать несколькими средствами, а не одним браузерным флагом. **BFF: когда токен вообще не попадает в браузер** Самым безопасным браузерным токеном часто является токен, который никогда не попадает в браузер. Backend for Frontend (BFF) — это серверный слой, предназначенный для конкретного клиентского приложения. Браузер взаимодействует с BFF, а BFF уже общается с основным API. Пользователь проходит аутентификацию через BFF. Токены доступа и обновления остаются на сервере. Браузер получает только HttpOnly-куки сессии. Клиентские запросы отправляются в BFF, который при необходимости добавляет токен доступа перед обращением к API. Браузер никогда не обрабатывает реальные токены OAuth. Даже если на странице выполняется вредоносный JS, он не может прочитать токен, существующий только в серверном хранилище сессий. BFF может хранить данные сессии в Redis, базе данных или другой защищённой серверной системе. Браузер хранит только непрозрачный идентификатор. Такой подход усложняет сервер, но даёт гораздо больший контроль над хранением токена, его ротацией, отзывом и мониторингом использования. Браузер получает только непрозрачный куки, доступ к учётным данным через JS не требуется, токены OAuth остаются в серверном хранилище. Это позволяет извлекать токены после XSS, централизованно обновлять, отзывать и логировать их. Плата за это — необходимость серверного слоя с состоянием и координация обновления и повторной отправки на клиенте. **Передача токенов: заголовок или куки** После выпуска и хранения учётные данные добавляются к запросам. Два распространённых подхода — заголовок Authorization и куки. Bearer-токен обычно указывается в заголовке Authorization: Bearer **Отзыв токенов и обнаружение угроз** Полный жизненный цикл токена включает не только выпуск и использование, но и возможность быстро отозвать доступ. Короткоживущие токены доступа ограничивают окно атаки, но для немедленного прерывания сессии нужны механизмы отзыва. Токены обновления должны меняться атомарно при каждом использовании: старый токен становится недействительным, выдаётся новый. Это предотвращает повторное использование украденного токена обновления. Если токен обновления скомпрометирован, его можно отозвать принудительно, аннулировав всю сессию. Важно иметь возможность отозвать любую сессию — как по инициативе пользователя (выход из системы), так и по подозрению в компрометации. Для этого нужно хранить информацию о сессиях на сервере, а не только полагаться на подпись JWT. Мониторинг использования токенов, аномальное поведение, одновременные входы из разных географических точек — всё это помогает обнаружить угрозу до того, как будут совершены серьёзные действия. **Итоговая архитектура** Используйте короткоживущие токены доступа, не храните токены обновления в хранилищах, доступных для чтения через JavaScript, меняйте токены обновления атомарно и имейте возможность отозвать любую сессию. Для браузерных приложений поток кода авторизации с PKCE плюс бэкенд для фронтенда и сессия в HttpOnly-куки предоставляют сильную начальную архитектуру. Такой подход минимизирует поверхность атаки: токены не видны скриптам, короткий срок жизни ограничивает ущерб от кражи, атомарная ротация и отзыв позволяют быстро реагировать на инциденты. Безопасность токена — это не только алгоритм подписи. Это весь жизненный цикл: от правильного выбора потока OAuth до хранения, передачи, обновления и отзыва. Каждое решение в этой цепочке влияет на устойчивость системы к реальным атакам. А как выстроена аутентификация в ваших приложениях? Храните ли вы токены в localStorage или уже используете BFF с HttpOnly-куки? Поделитесь опытом в комментариях — возможно, именно ваш подход поможет другим избежать типичных ошибок. Телеграм: t.me/ainewsline Источник: vk.com Комментарии: |
|