OAuth 2.0

27 июня 2026 · ~15 мин чтения

протокол авторизация веб безопасность api

OAuth 2.0

Открытый протокол, позволяющий одному приложению получить ограниченный доступ к ресурсам пользователя в другом приложении — без передачи логина и пароля. Вместо них передаётся выписанный для конкретного приложения токен.

История

OAuth родился из конкретной боли — соцсетей середины 2000-х. К 2006 году у людей появились десятки сервисов: Twitter, Flickr, Google Calendar, Delicious. Каждый раз, когда сторонняя программа хотела «постить за тебя» или «забрать твою адресную книгу», она просила логин и пароль. Это было ужасно: пользователь отдавал ключи от всего, а отозвать доступ можно было только сменой пароля — и тогда отваливались все приложения сразу.

Осенью 2006 года Blaine Cook (тогда — главный архитектор Twitter) и Chris Messina (тот самый, что придумал хештеги) встретились и поняли: им нужен общий стандарт делегирования доступа. К декабрю 2006-го собралась группа из нескольких компаний — Twitter, Magnolia, Pownce, Jaiku — и в апреле 2007-го они выкатили первый драфт OAuth 1.0. В декабре 2007-го протокол опубликовали официально.

В 2009-м нашли дыру — session fixation attack — и выпустили OAuth 1.0a. Параллельно стало понятно, что 1.0 слишком сложен: требовал криптографическую подпись каждого запроса HMAC-SHA1, что хорошо для безопасности, но плохо для разработчиков. Особенно мобильных разработчиков и тех, кто работал на стороне браузера.

В 2010-м IETF (это организация, которая выпускает RFC — основные документы интернет-стандартов) собрала рабочую группу для версии 2.0. Лидом редактора был Eran Hammer — программист, который писал OAuth 1.0 и был его главным апологетом. И вот тут случилась знаменитая драма.

В июле 2012-го, за несколько месяцев до публикации RFC, Hammer демонстративно ушёл с поста, опубликовав разгромный пост «OAuth 2.0 and the Road to Hell» («OAuth 2.0 и дорога в ад»). Он обвинял корпоративных участников (Microsoft, Salesforce и других) в том, что они превратили компактный протокол в швейцарский нож с десятком опций, где каждый делает по-своему и итоговая безопасность зависит от того, как именно ты собираешь все эти детали. Hammer сравнил это с проклятием WS-* — стандартами «энтерпрайз-сервисов» 2000-х, известными именно тем, что в них никто никогда до конца не разобрался.

Несмотря на скандал, в октябре 2012 года вышел RFC 6749 — The OAuth 2.0 Authorization Framework. Именно его сегодня все имеют в виду, когда говорят «OAuth». Это framework, а не протокол в строгом смысле: он описывает не один поток, а несколько, и оставляет много мест на усмотрение реализации.

С тех пор было много дополняющих RFC: RFC 6750 (Bearer Tokens), RFC 7636 (PKCE — обязательная защита для мобильных и SPA), RFC 8252 (для нативных приложений). Сейчас идёт работа над OAuth 2.1 — это не новая версия, а консолидация: убрать устаревшие потоки (Implicit Grant, Resource Owner Password Credentials), сделать PKCE обязательным везде, прибить лучшие практики гвоздями. Драфта 12 опубликован в 2024-м, финальный RFC — ещё в работе.

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

Что это такое

Главная мысль OAuth: разделить три вещи, которые раньше путали.

Аутентификация — кто ты. Это пароль и логин.
Авторизация — что тебе разрешено. Это право читать, писать, удалять.
Делегирование — ты разрешаешь кому-то третьему действовать от твоего имени, в ограниченных рамках.

Классическая ошибка — путать OAuth с «системой входа». Сам по себе OAuth этого не делает: он не говорит «вот этот пользователь — Паша». Он говорит «вот это приложение получило разрешение на чтение календаря пользователя такого-то». Для «опознать пользователя» нужен OpenID Connect, надстройка над OAuth.

В OAuth 2.0 четыре участника:

Authorization Server и Resource Server часто живут в одной компании, но это разные серверы и часто разные домены. Это важно: токен ты получаешь у одного, а используешь — у другого.

И главный артефакт всей системы — access token. Это короткая строка (обычно случайная либо JWT — об этом ниже), которую клиент прикладывает к каждому запросу: Authorization: Bearer <токен>. Сервер ресурсов проверяет токен и отвечает.

В чём отличие от старого «дай свой пароль приложению»:
- Токен выдан только этому конкретному клиенту (если украли — отозвал только у одного).
- Токен ограничен по правам (scope — об этом ниже).
- Токен ограничен по времени (живёт час-сутки-год, в зависимости от настройки).
- Токен отозвать проще, чем сменить пароль.

OAuth 2.0 vs OAuth 1.0a: 1.0a требовал подписывать каждый запрос. Безопаснее в каналах без HTTPS, но требовал криптографии в клиенте. 2.0 убрал подписи и опёрся на HTTPS — стало проще писать клиентов, но любой утёкший токен сразу даёт доступ.

OAuth vs SAML: SAML — это XML-протокол примерно того же возраста, родом из корпоративного мира (логины во внутренние системы крупных компаний). Делает похожее, но через громоздкие XML-документы и тяжелее в реализации. Сегодня в b2c-вебе SAML почти умер, в b2b ещё жив — крупные корпорации требуют SAML SSO для своих сотрудников.

OAuth vs API-ключ: API-ключ — простая строка, которую дают навсегда и обычно с правами на всё. OAuth-токен — выписан на конкретного пользователя, с конкретными правами, на ограниченный срок. API-ключ удобен для server-to-server (бэкенд ходит в чужой бэкенд), OAuth — для случаев, когда есть пользователь, и ты действуешь от его имени.

Аналогии из жизни

Гостиничная карта-ключ. Когда ты заселяешься, портье не отдаёт тебе мастер-ключ от всего отеля. Он выдаёт пластиковую карту, которая открывает только твой номер и работает до даты выезда. Если карту потеряешь — деактивируют только её, остальные гости спят спокойно. Если задержишься на день — нужно прийти и продлить. Точно так же OAuth-токен: ограниченный (только твой номер = только нужный scope), временный (живёт до выезда = срок жизни токена), легко отзываемый.

Где ломается: в отеле есть физический контроль на ресепшене — никто не подделает карту, потому что замки её распознают физически. В OAuth такого контроля нет: если ты случайно слил токен в чат или закоммитил в публичный гитхаб — кто угодно с ним зайдёт «в твой номер», пока его не отзовут. Карту-ключ из чужого кармана достать сложнее, чем строку из лога.

Доверенность у нотариуса. Ты выписываешь брату доверенность: «может получить мою посылку на почте, действует до 31 декабря». Брат идёт на почту, показывает доверенность, ему выдают посылку. Почта не звонит тебе и не проверяет лично — она доверяет печати нотариуса. Аналогично, ресурс-сервер не звонит пользователю, а доверяет токену, выданному сервером авторизации.

Где ломается: доверенность — на конкретное действие («получить посылку»). В OAuth scope бывает очень широким — например, scope «email» в Google означает «читай весь почтовый ящик». Если ты дал такой scope, ты «выписал доверенность на квартиру» там, где хотел только посылку забрать. Поэтому при логине через Google всегда читай, что именно разрешаешь.

Бейдж посетителя в офисе. Приходишь в офис, охранник сверяет паспорт (это аутентификация), выписывает временный пропуск с QR-кодом — «гость такой-то, этаж 5, до 18:00» (это OAuth-токен). Внутри уже никто не спрашивает паспорт — только сканируют пропуск. Если ты захотел в серверную на 8-м этаже, сканер пишет «не положено» (несоответствие scope). В конце дня пропуск перестаёт работать сам — это expiry токена.

Где ломается: бейдж в офисе обычно с фотографией, и охранник может сличить. В OAuth носителем токена может быть кто угодно — это так называемый bearer token (то есть «на предъявителя»). Прибил физически к одному устройству — это уже другие механизмы, DPoP или mTLS, и они применяются редко.

Как это работает

OAuth 2.0 описывает не один поток, а несколько — они называются grant types (типы получения токена). Самый распространённый и важный — Authorization Code Grant с PKCE. Разберём именно его, остальные — упомяну в конце.

Сценарий: ты сидишь на сайте AnalyticsTool (это клиент), он хочет читать твою Яндекс.Метрику.

Шаг 0 — заранее: разработчик AnalyticsTool пошёл к Яндексу, зарегистрировал приложение, получил пару client_id (публичный — что-то вроде «привет, я приложение №12345») и client_secret (секретный — пароль приложения, которым оно подтверждает, что это действительно оно). Указал redirect_uri — куда возвращать пользователя после согласия (https://analyticstool.example/oauth/callback).

Шаг 1 — отправка пользователя на согласие. Ты на AnalyticsTool жмёшь «Подключить Яндекс.Метрику». Клиент перенаправляет тебя в браузере на:

https://oauth.yandex.ru/authorize?
  response_type=code&
  client_id=ABC123&
  redirect_uri=https://analyticstool.example/oauth/callback&
  scope=metrika:read&
  state=xyz789&
  code_challenge=...&
  code_challenge_method=S256

Тут важные параметры. response_type=code — «верни мне authorization code» (это «однократная купонная бумажка», а не сам токен). scope — какие права просит клиент. state — случайная строка от клиента, защита от CSRF (клиент потом проверит, что state в ответе тот же). code_challenge — кусок PKCE-защиты, расскажу через секунду.

Шаг 2 — Яндекс показывает экран согласия. Это та самая страница «AnalyticsTool хочет получить доступ: чтение данных Метрики». Если ты не залогинен в Яндекс — сначала логин. Если залогинен — сразу видишь список прав и кнопки «Разрешить»/«Отказать».

Шаг 3 — редирект обратно с authorization code. Жмёшь «Разрешить» — Яндекс делает 302-редирект в твоём браузере:

https://analyticstool.example/oauth/callback?code=TEMP_CODE_qwe123&state=xyz789

TEMP_CODE_qwe123 — это authorization code. Жив ~10 минут, использовать можно один раз.

Шаг 4 — клиент меняет код на токен. AnalyticsTool сервер (не браузер!) делает прямой POST на https://oauth.yandex.ru/token:

POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=TEMP_CODE_qwe123
&client_id=ABC123
&client_secret=SECRET_SAUCE
&redirect_uri=https://analyticstool.example/oauth/callback
&code_verifier=...

Это уже не в браузере, а сервер-к-серверу. Здесь клиент доказывает, что это действительно он (client_secret), и присылает code_verifier — вторую часть PKCE.

Шаг 5 — Яндекс возвращает токены.

{
  "access_token": "y0_AgAAAAA...",
  "token_type": "bearer",
  "expires_in": 31536000,
  "refresh_token": "1::..."
}

access_token — главный артефакт, его клиент будет прикладывать к запросам. expires_in — секунд до истечения (в этом примере — год; у Яндекса так и есть, у Google access_token обычно живёт час). refresh_token — выдаётся, чтобы потом получить новый access без участия пользователя.

Шаг 6 — клиент пользуется токеном.

GET https://api-metrika.yandex.net/management/v1/counters
Authorization: OAuth y0_AgAAAAA...

Технически правильно Authorization: Bearer ..., но Яндекс исторически принимает OAuth ... — это легаси с тех времён, когда они начинали с черновика стандарта.

Шаг 7 — токен умер, обновляемся. Через год (или через час, у разных сервисов по-разному) клиент получит:

{"errors":[{"error_type":"invalid_token","message":"Invalid oauth_token"}],"code":403}

Тогда клиент идёт обновлять — POST с grant_type=refresh_token&refresh_token=.... Если refresh жив (а он живёт ещё дольше) — выписывают новый access. Если и refresh умер — придётся вести пользователя через весь поток заново.

Что такое PKCE и зачем. PKCE (произносят «пикси», Proof Key for Code Exchange) — защита от перехвата authorization code. Клиент перед шагом 1 генерирует случайный code_verifier, хэширует его в code_challenge и отправляет challenge в запросе авторизации. Через несколько шагов, обменивая код на токен, присылает verifier. Сервер проверяет, что SHA256(verifier) == challenge. Если кто-то перехватил код посередине (например, через зловредную apk на телефоне) — без verifier'а ему ничего не светит. С 2024-го PKCE — обязательная практика для всех типов клиентов, не только мобильных.

Другие grant types (коротко):

Где встречается в обычной жизни

Где встречается в IT и бизнесе

Кто пользуется

OAuth 2.0 — фактический стандарт интернета. По данным Authlete (одна из компаний, продающих OAuth-инфраструктуру), на 2023 год протокол поддерживают практически все крупные интернет-сервисы: Google, Microsoft, Apple, Facebook/Meta, Amazon, GitHub, GitLab, Atlassian, Slack, Notion, Figma, Adobe, Spotify, Twitter/X, Reddit, LinkedIn, Salesforce, Zoom — продолжать можно очень долго.

В России: Яндекс (oauth.yandex.ru), VK (oauth.vk.com), Сбер (sber id), Mail.ru. Mos.ru, Госуслуги выдают свои OAuth-токены — на них завязана половина государственных интеграций.

Масштабы — миллиарды токенов в день. Только Google отдаёт оценочно сотни миллионов access_token'ов в сутки своим OAuth-приложениям (точную цифру публично они не называют). На рынке есть отдельные продукты, которые ничего, кроме OAuth, не делают: Auth0 (куплен Okta в 2021 за 6,5 млрд $), Stytch, FusionAuth, отечественные Keycloak (Red Hat / опенсорс), Ory Hydra.

Альтернативы и конкуренты

SAML 2.0. Корпоративный стандарт делегированной аутентификации на XML. Плюсы: десятилетняя зрелость, поддержка enterprise SSO-решений (Okta, OneLogin, ADFS). Минусы: тяжёлый XML, нерасчитан на мобильные клиенты, сложно отлаживать.

API-ключи. Простая строка, обычно навсегда. Плюсы: дёшево и просто, отлично для server-to-server. Минусы: нет понятия «пользовательский контекст», нет короткого срока жизни, нет scope'ов.

JWT + кастомная авторизация. Многие сервисы выпускают свои JWT и обходятся без OAuth-фреймворка вообще. Плюсы: меньше зависимостей, полный контроль. Минусы: придётся самому изобретать всё, что в OAuth уже придумано (отзыв токена, обновление, scope, согласие).

Magic-links / Passkeys / WebAuthn. Это про вход, а не делегирование. Часто их кладут поверх OAuth-инфраструктуры как способ аутентификации внутри Authorization Code Flow.

Когда НЕ стоит использовать

Грабли с токенами в публичных репозиториях

OAuth-токен — это bearer, «на предъявителя». Если он попал в публичный гитхаб, gist, скриншот в чате — считай, его уже скачали боты. GitHub секрет-сканнер автоматически уведомляет Google/Slack/Stripe о найденных в коде токенах, и они часто отзывают токен сами. Но не все провайдеры это делают. Перед коммитом — проверь, что токен идёт через переменную окружения, не через хардкод.

Связанные понятия

Литература и источники

Где встретилось у меня

Вчера разбирались с Яндекс.Метрикой. Старый OAuth-токен для одного аккаунта оказался отозванным (invalid_token, 403), пришлось искать рабочий среди переменных окружения и параллельно соображать, есть ли вообще доступ к новому счётчику. Под разговор всплывали client_id, client_secret, scope'ы и сам URL oauth.yandex.ru/authorize — то есть всё семейство понятий OAuth 2.0, с которым работает любая интеграция.

Краткое резюме