OAuth 2.0 и OpenID Connect: как настроить безопасную авторизацию в API
сен, 3 2026
Знаете это чувство, когда вы пишете свой первый микросервис и понимаете, что логин «admin/123456» уже не спасает? Пользователи хотят заходить через Google, мобильные приложения требуют сессии без паролей, а партнеры просят доступ к вашим данным, но вы боитесь отдавать им ключи от всего сервера. Тут на сцену выходят OAuth 2.0 и OpenID Connect (OIDC). Многие новички путают эти два стандарта, считая их взаимозаменяемыми. На самом деле, OAuth 2.0 отвечает за то, кто имеет право делать действия, а OIDC - за то, кто этот пользователь. Разберемся, как они работают вместе, чтобы ваш API дышал ровно, а безопасность не превращалась в административный кошмар.
В чем разница между аутентификацией и авторизацией?
Прежде чем копаться в протоколах, давайте договоримся о терминах. Это база, которую часто игнорируют, а потом удивляются дырам в безопасности.
Аутентификация - это процесс проверки личности. Вы говорите системе: «Я Иван». Система проверяет паспорт (пароль, биометрию, токен) и подтверждает: «Да, ты действительно Иван». Это вопрос доверия к идентичности.
Авторизация - это проверка прав. Система спрашивает: «Иван, тебе можно удалять файлы?» или «Можно ли приложению X читать твою почту?». Здесь мы работаем с разрешениями и scope'ами.
Классическая ошибка - использовать один механизм для обоих случаев. Раньше все было просто: сессия cookie + хеш пароля. Но когда у вас есть мобильное приложение, SPA (Single Page Application) и сторонние сервисы, которые должны общаться с вашим бэкендом, старая схема ломается. Именно поэтому появился OAuth 2.0. Он не занимается аутентификацией напрямую, он дает вам «пропуск» (токен доступа), который позволяет выполнять действия от имени пользователя, не передавая сам пароль.
OAuth 2.0: как это работает на практике
Представьте, что вы хотите заказать такси через приложение, которое использует карты Яндекс. Вам нужно дать приложению доступ к вашему геолокационному профилю, но вы не хотите давать ему свой пароль от Яндекса. Вы нажимаете «Войти через Яндекс», открывается окно авторизации, вы соглашаетесь, и приложение получает временный ключ.
Этот процесс описывается ролями, которые определены в спецификации RFC 6749:
- Resource Owner - вы, пользователь, которому принадлежат данные.
- Client - приложение, которому нужны права (например, ваше мобильное приложение).
- Authorization Server - сервис, который проверяет вашу личность и выдает токены (ваш бэкенд или Keycloak/Auth0).
- Resource Server - API, который хранит данные и принимает запросы с токенами.
Самый популярный поток сейчас - Authorization Code Flow with PKCE. Почему PKCE? Потому что современные клиенты (SPA и мобильники) не могут безопасно хранить секрет клиента в коде. PKCE добавляет случайный код верификатора, который перехватчик не сможет подделать. Без этого шага ваш токен легко украсть из URL-адреса браузера.
OpenID Connect: слой поверх OAuth 2.0
Если OAuth 2.0 говорит «ты можешь читать мои данные», то OpenID Connect добавляет слой идентификации, возвращая информацию о пользователе в виде JSON Web Token (JWT). OIDC - это надстройка над OAuth 2.0. Он использует тот же механизм выдачи токенов, но вместо простого Access Token возвращает ID Token.
ID Token содержит утверждения (claims) о пользователе: его уникальный идентификатор (sub), имя, email, время входа. Ваша задача на бэкенде - проверить подпись этого токена и убедиться, что он выдан доверенным провайдером. Это позволяет реализовать Single Sign-On (SSO): пользователь вошел один раз в систему, и все ваши микросервисы знают, кто он такой, без повторных вводов пароля.
| Характеристика | OAuth 2.0 | OpenID Connect |
|---|---|---|
| Основная цель | Авторизация (доступ к ресурсам) | Аутентификация (идентификация пользователя) |
| Тип токена | Access Token (обычно opaque или JWT) | ID Token (всегда JWT) |
| Данные о пользователе | Нет встроенного механизма | Есть (Claims: name, email, picture) |
| Endpoint | /token, /authorize | /userinfo (дополнительно) |
| Использование | API-шлюзы, интеграции с третьими сторонами | Логин пользователей, SSO |
Где хранить токены и как избежать XSS
Самый горячий спор среди фронтендеров и бэкендеров: где хранить токен? В localStorage или в httpOnly cookie?
Если вы выберете localStorage, вы рискуете получить атаку XSS (Cross-Site Scripting). Если злоумышленник внедрит скрипт на вашу страницу, он сможет прочитать localStorage и украсть токен. Для SPA это частая проблема.
Более безопасный вариант для современных приложений - использование httpOnly cookies. Браузер не дает JavaScript'у читать такие куки, поэтому XSS не сможет их украсть. Однако здесь возникает другая проблема: CSRF (Cross-Site Request Forgery). Чтобы защититься от нее, нужно использовать атрибут SameSite=Lax или Strict и проверять Origin заголовков на бэкенде.
Для мобильных приложений ситуация проще: там нет браузерной песочницы в том же смысле, поэтому хранение в защищенном хранилище устройства (Keychain на iOS, Keystore на Android) - стандарт де-факто.
Refresh Tokens: продлеваем жизнь сессии
Access Token должен жить недолго. Обычно 15-60 минут. Зачем так мало? Чтобы минимизировать ущерб, если токен украдут. Но каждые 15 минут просить пользователя вводить пароль - путь в никуда. Тут на помощь приходит Refresh Token.
Когда срок жизни Access Token истекает, клиент отправляет Refresh Token на endpoint /token с параметром grant_type=refresh_token. Сервер проверяет его, перевыпускает новый Access Token (и иногда новый Refresh Token) и отдает обратно. Пользователь даже не замечает подмены.
Важный нюанс: Refresh Token тоже нужно ротировать. Если вы выдали Refresh Token, использовали его и получили новый, старый должен стать невалидным. Это защищает от ситуации, когда украденный Refresh Token используется бесконечно долго.
Практические советы по внедрению
Не пытайтесь писать свой сервер авторизации с нуля, если у вас нет избытка времени и желания читать RFC по ночам. Используйте готовые решения. Для небольших проектов подойдет Auth0 или Firebase Authentication. Для enterprise или self-hosted решений посмотрите в сторону Keycloak или IdentityServer.
Вот чек-лист перед релизом вашего API:
- HTTPS везде. Никаких исключений. Токены летят в открытом тексте, если канал не шифрован.
- Проверяйте Audience (aud). Убедитесь, что токен предназначен именно для вашего API. Иначе пользователь может предъявить токен от другого сервиса.
- Ограничьте Scope. Не давайте всем все права. Если приложению нужен только профиль, пусть оно запрашивает scope
profile, а неadmin. - Логируйте ошибки авторизации. Понимание того, почему пользователи не могут войти, экономит часы поддержки.
Помните, что безопасность - это не функция, которую можно включить галочкой. Это непрерывный процесс. Стандарты меняются, уязвимости находят регулярно. Следите за обновлениями спецификаций и обновляйте библиотеки.
Нужен ли мне OpenID Connect, если я делаю только API для своего мобильного приложения?
Если ваше мобильное приложение само управляет регистрацией и логином (email/password), вам достаточно OAuth 2.0 для получения токенов доступа к вашему бэкенду. OpenID Connect становится необходим, когда вы хотите добавить вход через социальные сети (Google, Facebook) или единый вход (SSO) между несколькими вашими приложениями. OIDC стандартизирует получение данных профиля пользователя после успешной авторизации.
Что такое JWT и всегда ли он лучше opaque токена?
JWT (JSON Web Token) - это компактный способ передачи информации в виде JSON объекта, подписанного криптографически. Его преимущество в том, что Resource Server может проверить подпись и извлечь данные (user_id, roles) локально, без обращения к Authorization Server на каждый запрос. Это снижает нагрузку. Однако JWT сложнее отзывать досрочно (logout), так как он стейтлесс. Opaque token требует проверки на сервере, что медленнее, но позволяет мгновенно блокировать доступ. Для большинства высоконагруженных систем выбор падает на JWT с коротким сроком жизни.
Как защитить токен от кражи при использовании localStorage?
Защита от XSS в localStorage сложна, потому что любой скрипт на странице может прочитать данные. Основные меры: строгая политика CSP (Content Security Policy), которая запрещает выполнение инлайн-скриптов и загружает JS только с ваших доменов; регулярное обновление токенов; и использование HttpOnly cookie вместо localStorage, если архитектура позволяет. Если вы обязаны использовать localStorage, убедитесь, что ваш код полностью изолирован от внешних библиотек, которые могут содержать уязвимости.
Что делать, если пользователь заблокировал аккаунт, а его токен еще живой?
Это классическая проблема stateless JWT. Поскольку токен не проверяется на сервере при каждом запросе, заблокированный пользователь может продолжать работу до истечения срока токена (например, 15 минут). Решения: 1) Использовать короткие сроки жизни токенов (5-10 минут). 2) Внедрить blacklist токенов в Redis (дорого по памяти). 3) Проверять статус пользователя в базе данных при критических операциях (оплата, удаление). 4) Использовать гибридный подход: JWT для обычных запросов, проверка БД для чувствительных действий.
Можно ли использовать один и тот же токен для разных микросервисов?
Да, но с осторожностью. Если все ваши микросервисы находятся под одним зонтиком безопасности и доверяют одному Authorization Server, они могут принимать один и тот же Access Token. Важно, чтобы в токене был указан правильный audience (aud), соответствующий вашему API Gateway или конкретному сервису. Если аудитория не совпадает, сервис должен отвергнуть запрос. Также следите за тем, чтобы scope'ы в токене были достаточными для всех операций, которые планируются в рамках одной сессии.