OAuth 2.0 и OpenID Connect

Материал из llmdocs — справочник разработчика
OAuth 2.0 и OpenID Connect
OAuth 2.0RFC 6749 (октябрь 2012)
OpenID ConnectOpenID Connect Core 1.0 (OpenID Foundation, 2014)
Следующая версияOAuth 2.1 (черновик IETF)
Токеныaccess token, refresh token, ID token (JWT)
Основной потокAuthorization Code + PKCE
Роливладелец ресурса, клиент, сервер авторизации, сервер ресурсов
РеализацииKeycloak, Authentik, Ory Hydra, Auth0, Яндекс ID, VK ID

OAuth 2.0 — открытый протокол делегирования доступа: он позволяет приложению получить ограниченный доступ к ресурсам пользователя в другом сервисе (почте, календарю, репозиториям), не узнавая его пароля. Вместо пароля приложение получает токен доступа с ограниченными правами и сроком жизни. OpenID Connect (OIDC) — слой поверх OAuth 2.0, который добавляет аутентификацию: подтверждённые сведения о том, кто именно вошёл. Кнопки «Войти через Яндекс», «Войти через GitHub» работают на OIDC или близких к нему схемах. Разница между проверкой личности и проверкой прав разобрана в статье Аутентификация и авторизация.

История

До OAuth сторонние сервисы просили у пользователя логин и пароль от почты, чтобы, например, импортировать контакты, — это давало им полный доступ к аккаунту. OAuth 1.0 (2007, RFC 5849) решил задачу, но требовал сложной криптографической подписи каждого запроса. OAuth 2.0 (2012) упростил протокол, переложив защиту канала на TLS, и стал «рамкой» с несколькими сценариями (grant types).[1] Поскольку OAuth сам по себе не говорит, кто пользователь, компании изобретали собственные надстройки, пока OpenID Foundation не выпустила в 2014 году OpenID Connect.[4]

Роли

Роль Пример
Владелец ресурса (resource owner) пользователь
Клиент (client) ваше веб-приложение или мобильная программа
Сервер авторизации (authorization server) oauth.yandex.ru, Keycloak
Сервер ресурсов (resource server) API, принимающее токены

Клиент заранее регистрируется у сервера авторизации и получает client_id (и для серверных приложений — client_secret), а также указывает разрешённые адреса возврата (redirect URI).

Поток Authorization Code с PKCE

Основной и рекомендуемый для всех типов клиентов сценарий:[3]

  1. Клиент генерирует случайный code_verifier и его хеш code_challenge (PKCE).[2]
  2. Браузер пользователя перенаправляется на сервер авторизации с параметрами client_id, redirect_uri, scope (запрашиваемые права), state (защита от CSRF) и code_challenge.
  3. Пользователь входит и соглашается выдать права.
  4. Сервер перенаправляет браузер обратно на redirect_uri с одноразовым кодом авторизации.
  5. Клиент обменивает код на токены прямым запросом к серверу, прикладывая code_verifier. Перехваченный код без него бесполезен.
POST /token HTTP/1.1
Host: auth.example.ru
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQ&redirect_uri=https%3A%2F%2Fapp.example.ru%2Fcb
&client_id=app&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

В ответ приходит JSON с access_token, сроком жизни expires_in, при необходимости refresh_token, а в OIDC — ещё и id_token.

Другие сценарии: Client Credentials — сервис обращается к API от своего имени, без пользователя; Device Authorization — вход на телевизоре или в консольной утилите по коду, введённому на телефоне.[7] Устаревшие сценарии Implicit (токен прямо в URL) и Password (клиент собирает пароль) в OAuth 2.1 удалены.[5]

Токены

  • Access token — предъявляется API в заголовке Authorization: Bearer …. Может быть непрозрачной строкой (сервер проверяет её запросом introspection) или самодостаточным JWT с подписью. Живёт минуты или часы.
  • Refresh token — долгоживущий, позволяет получить новый access token без участия пользователя. Хранится только у клиента и должен быть защищён.
  • ID token (OIDC) — подписанный JWT[6] с полями iss (кто выдал), sub (постоянный идентификатор пользователя), aud (для какого клиента), exp, nonce и, по запросу, email, name. Клиент обязан проверить подпись и эти поля.

OIDC добавляет также эндпоинт /userinfo, стандартные scope (openid, profile, email) и документ discovery по адресу /.well-known/openid-configuration, из которого библиотеки автоматически узнают адреса и ключи сервера.

Безопасность

Типичные ошибки — неточная проверка redirect_uri (позволяет украсть код), отсутствие state/PKCE, хранение токенов в localStorage при уязвимости к XSS, использование access token как доказательства входа без проверки aud. Сводные рекомендации собраны в RFC 9700.[3] Для браузерных приложений часто используют схему BFF (backend for frontend): токены держит сервер, а браузер получает обычную сессионную cookie.

В России для публичных сервисов действуют требования об авторизации пользователей через российские сервисы (Яндекс ID, VK ID, Госуслуги, номер телефона) — они тоже реализуют OAuth 2.0 и, в разной степени, OIDC.

См. также

Источники

  1. RFC 6749 — The OAuth 2.0 Authorization Framework
  2. RFC 7636 — Proof Key for Code Exchange (PKCE)
  3. RFC 9700 — Best Current Practice for OAuth 2.0 Security
  4. OpenID Connect Core 1.0
  5. The OAuth 2.1 Authorization Framework (draft)
  6. RFC 7519 — JSON Web Token (JWT)
  7. RFC 8628 — OAuth 2.0 Device Authorization Grant