Представьте: вы хотите, чтобы стороннее приложение (например, сервис подбора фотографий) залезло в ваш фотоальбом в облаке. Отдавать ему ваш логин и пароль от облака — плохая идея: он получит полный доступ ко всему, и пароль придётся менять у всех сразу, если он утечёт. Нужен способ выдать ограниченный, отзываемый доступ без передачи пароля. Именно эту задачу решает OAuth2, а OIDC добавляет к ней ответ на вопрос «а кто, собственно, этот пользователь».
Зачем вообще OAuth2: проблема «отдать пароль»
Старый способ — дать приложению свой пароль — ломается сразу по нескольким причинам:
- приложение видит ваш пароль (а значит, может всё);
- доступ нельзя ограничить — «только чтение фотографий» не выразить;
- отозвать доступ у одного приложения нельзя, не меняя пароль везде.
OAuth2 — это протокол делегирования доступа. Вы разрешаете приложению действовать от вашего имени в строго оговорённых рамках, не показывая ему пароль. Вместо пароля приложение получает токен — временный «пропуск» с ограниченными правами, который в любой момент можно отозвать.
Ключевая мысль: OAuth2 — про доступ (что приложению разрешено делать), а не про вашу личность.
Четыре роли OAuth2 на аналогии с отелем
В OAuth2 всегда четыре участника. Разберём их на аналогии: вы заселяетесь в отель.
- Владелец ресурса (resource owner) — это вы, гость. Ресурс — ваш номер; именно вы решаете, кто туда войдёт.
- Сервер авторизации (authorization server) — стойка регистрации. Вы показываете паспорт, и вам выдают ключ-карту. Стойка проверяет, кто вы, и решает, что вам можно.
- Клиент (client) — приложение, которому нужен доступ. В аналогии это уборщик или служба доставки еды, которому вы разрешили заходить в номер. Он не владелец, он действует с вашего разрешения.
- Сервер ресурсов (resource server) — дверной замок номера. Он не знает вас лично, он просто проверяет: подходит ключ-карта — пускает, не подходит — нет.
Связка простая: владелец ресурса (вы) разрешает на сервере авторизации (стойке) выдать клиенту (уборщику) ключ-карту (токен), а сервер ресурсов (замок) пускает по этой карте.
В терминах реальной системы: стоит сервер авторизации (например, Keycloak), есть ваше приложение (клиент), есть API с данными (сервер ресурсов), и есть вы (владелец ресурса).
Access token: пропуск для доступа к API
Проблема: API должно как-то понять, что входящий запрос разрешён, не спрашивая каждый раз пароль.
Access token (токен доступа) — это и есть ключ-карта. Клиент прикладывает его к каждому запросу к API, обычно в заголовке:
GET /albums/42/photos
Authorization: Bearer eyJhbGciOiJSUzI1Niis...
Свойства access token, которые важно понимать:
- короткоживущий — обычно минуты (часто 5–15). Если утечёт, ущерб ограничен по времени.
- несёт scope (об этом ниже) — какие именно действия разрешены.
- сервер ресурсов проверяет его сам, не дёргая каждый раз сервер авторизации (если токен — подписанный JWT, проверяется подпись).
Access token адресован серверу ресурсов (API). Это «пропуск делать», а не «удостоверение личности».
Refresh token: чтобы не логиниться каждые 10 минут
Проблема: если access token живёт 10 минут, пользователю пришлось бы заново вводить логин и пароль каждые 10 минут. Это невыносимо.
Refresh token (токен обновления) решает это. Он живёт долго (часы, дни, иногда дольше) и хранится в безопасном месте на стороне клиента. Когда access token истекает, клиент молча обменивает refresh token на новый access token — без участия пользователя.
POST /token
grant_type=refresh_token
refresh_token=<длинный-токен>
Зачем такое разделение «короткий + длинный»:
- access token часто гуляет по сети (в каждом запросе к API) — поэтому он короткий, чтобы кража быстро обесценилась;
- refresh token почти не двигается (только при обновлении) и хранится бережнее — поэтому может жить долго;
- refresh token можно отозвать на сервере авторизации, и тогда клиент больше не сможет обновлять доступ.
Refresh token адресован серверу авторизации — только он умеет его принять и выдать новый access token.
ID token и OIDC: ответ на вопрос «кто ты»
Тут важная развилка. OAuth2 сам по себе ничего не говорит о личности пользователя. Access token отвечает на вопрос «что можно делать», но не на вопрос «кто это». Если приложение хочет показать «Здравствуйте, Анна» — из чистого OAuth2 это надёжно не вытащить (access token формально вообще непрозрачен для клиента).
OIDC (OpenID Connect) — это тонкая надстройка над OAuth2, которая добавляет аутентификацию: способ узнать и доказать, кто пользователь. Делает она это через третий тип токена.
ID token — это всегда JWT (подписанный JSON), который описывает пользователя. Внутри — набор полей (claims):
{
"iss": "https://keycloak.example.com/realms/myrealm",
"sub": "a1b2c3d4-...",
"aud": "my-web-app",
"exp": 1735690000,
"iat": 1735689700,
"name": "Анна Иванова",
"email": "anna@example.com"
}
Что значат ключевые поля:
iss(issuer) — кто выдал токен (адрес сервера авторизации).sub(subject) — стабильный уникальный идентификатор пользователя. Именно он, а не email, — настоящий «ключ» пользователя.aud(audience) — для какого приложения токен предназначен. Чужойaudпринимать нельзя.exp/iat— когда истекает / когда выдан.
Главное правило, которое легко перепутать: ID token предназначен клиенту (приложению — чтобы узнать пользователя), access token — серверу ресурсов (API — чтобы решить, пускать ли). Не используйте ID token для доступа к API и не пытайтесь читать содержимое access token как профиль пользователя.
OAuth2 против OIDC: одной фразой
Их постоянно путают, поэтому зафиксируем разницу:
- OAuth2 — про авторизацию (доступ). «Этому приложению разрешено читать мои фотографии.» Инструмент — access token.
- OIDC — про аутентификацию (личность). «Этот пользователь — Анна, и это подтверждено сервером авторизации.» Инструмент — ID token.
OIDC не заменяет OAuth2, а достраивается поверх него: тот же поток получения токенов, но в ответ добавляется ID token и стандартные поля о пользователе. Когда вы видите кнопку «Войти через ...» — за ней почти всегда OIDC, а не голый OAuth2.
Scopes: ограничение «что именно можно»
Проблема: «дать доступ» — слишком грубо. Сервису подбора фотографий нужно только читать альбомы, а не удалять их и не лезть в платёжные данные.
Scope — это запрашиваемый объём прав, выраженный короткими метками. Клиент при входе говорит, что ему нужно, а пользователь это подтверждает (часто — на экране согласия):
scope=openid profile email albums:read
Здесь:
openid— особый scope: его наличие включает OIDC, то есть «выдай ещё и ID token». Безopenidэто просто OAuth2 без сведений о личности.profile,email— стандартные OIDC-наборы полей: имя, email и т.п. в ID token.albums:read— пример прикладного права для вашего API.
Полученный access token несёт согласованные scope, и сервер ресурсов по ним решает, что разрешить. Принцип — минимально необходимый доступ: просите только те scope, которые реально нужны.
Как это собирается вместе: Authorization Code Flow в двух словах
Самый распространённый способ получить токены для веб- и мобильных приложений называется Authorization Code Flow. В упрощённом виде:
- Приложение (клиент) отправляет пользователя на сервер авторизации на страницу входа.
- Пользователь вводит логин и пароль там же, на сервере авторизации — приложение их не видит.
- Сервер авторизации возвращает приложению одноразовый код авторизации (authorization code).
- Приложение на своём бэкенде обменивает этот код на токены: access token, refresh token и (если был scope
openid) ID token.
Важная деталь: пароль вводится только на сервере авторизации, а приложение получает не пароль, а короткоживущий код, который тут же меняет на токены. Для публичных клиентов (мобильные приложения, SPA) шаг обмена защищают механизмом PKCE, чтобы перехваченный код нельзя было использовать.
Это лишь общая картина — детали (зачем нужен код, как именно работает PKCE, как устроен экран согласия) разбираются в отдельной статье про Authorization Code Flow.
Коротко
- OAuth2 даёт приложению ограниченный отзываемый доступ без передачи пароля — это про доступ (авторизацию делегирования).
- Четыре роли: владелец ресурса (пользователь), клиент (приложение), сервер авторизации (выдаёт токены), сервер ресурсов (API, проверяет токены).
- Access token — короткоживущий пропуск к API, адресован серверу ресурсов.
- Refresh token — долгоживущий, обменивается на новый access token без участия пользователя, адресован серверу авторизации.
- ID token — всегда JWT о личности пользователя, адресован клиенту; появляется только с OIDC и scope
openid. - OIDC — надстройка над OAuth2 про аутентификацию («кто ты»); OAuth2 — про авторизацию («что можно»).
- Scopes ограничивают объём прав;
openidвключает OIDC,profile/emailдобавляют поля о пользователе. - Authorization Code Flow — основной способ получить токены: пароль вводится на сервере авторизации, приложение получает код и меняет его на токены.
Что почитать дальше
- Authorization Code Flow подробно — зачем нужен код, шаги потока и PKCE.
- JWT validation в Spring Security — как сервер ресурсов проверяет токен через
oauth2ResourceServerи JWK Set. - RBAC: маппинг ролей JWT и @PreAuthorize — как роли из токена превращаются в права на эндпоинтах.