OAuth 2.0 и JWT
Введение: временный пропуск 🎫
Представь: ты не отдаёшь другу ключи от квартиры. Ты даёшь ему временный пропуск.
OAuth 2.0 — это правила, как выдавать такой пропуск, а JWT — формат самого пропуска.
💡 Совет: пароль всегда остаётся у владельца, доступ выдаётся на время.
✅ Вывод: OAuth + JWT дают безопасный доступ без передачи пароля.
Проблема → решение
Проблема: внешним приложениям нужен доступ к данным пользователя, но отдавать пароль опасно.
Решение: OAuth 2.0 выдаёт access token с ограничениями, а JWT делает токен удобным и проверяемым.
✅ Вывод: доступ можно выдавать безопасно и контролируемо.
Чем помогает и как работает
OAuth помогает дать доступ только туда, куда нужно.
JWT помогает быстро проверить токен без запроса в базу.
Как это работает:
- Клиент получает разрешение у пользователя.
- Сервер авторизации выдаёт токен.
- API проверяет токен и пускает только по правилам.
✅ Вывод: доступ контролируется правилами, а пароль не раскрывается.
Ключевые термины (простыми словами)
- OAuth (Open Authorization — открытая авторизация) — правила выдачи доступа без пароля.
- Authorization Server (сервер авторизации) — место, где пользователь логинится и получает токены.
- Resource Server (сервер ресурсов) — API, которое защищаем.
- Client (клиент/приложение) — приложение, которое просит доступ.
- Authorization Code (код авторизации) — одноразовый код для обмена на токен.
- Access Token (токен доступа) — ключ для вызова API.
- Refresh Token (токен обновления) — ключ для получения нового access token.
- Scope (область доступа) — список разрешений.
- JWT (JSON Web Token — JSON‑токен) — формат токена с подписью.
- PKCE (Proof Key for Code Exchange — защита кода) — защита для публичных клиентов.
- State (состояние) — параметр защиты от подмены запроса.
Самое важное (must‑know)
- OAuth — это про доступ, а не про «кто ты». Для логина нужен OIDC.
- Для SPA и мобильных приложений используем Authorization Code + PKCE.
- Access token должен быть коротким по времени жизни.
- Refresh token долгий и хранится максимально безопасно.
- JWT подписан, но не шифруется по умолчанию.
- В браузере токены лучше хранить в HttpOnly cookies (Secure + SameSite).
1. OAuth 2.0 — выдача доступа без пароля
Назначение: дать приложению доступ к данным пользователя без передачи пароля.
Простыми словами: это правила, как попросить доступ и получить временный ключ.
Аналогия: гостевой пропуск на мероприятие.
Простыми словами: это правила, как попросить доступ и получить временный ключ.
Аналогия: гостевой пропуск на мероприятие.
Пример:
GET https://auth.example.com/oauth/authorize?response_type=code&client_id=web_app&redirect_uri=https://app.example.com/callback&scope=profile:read courses:read&state=xyz123🔎 Как это происходит на практике:
- Клиент отправляет пользователя на сервер авторизации.
- Пользователь подтверждает доступ.
- Сервер возвращает код, а API даёт токен.
Характеристики:
- ✅ пароль не передаётся приложению
- ✅ доступ ограничен scope‑ами
- ✅ есть роли: клиент, сервер авторизации, сервер ресурсов
Когда использовать: интеграции, мобильные клиенты, «Войти через Google».
✅ Вывод: OAuth безопасно выдаёт доступ без пароля.
2. Authorization Code + PKCE — безопасный вход
Назначение: безопасно получить токен в приложениях без client_secret.
Простыми словами: сначала берём одноразовый код, потом меняем его на токен.
Аналогия: взять талон и обменять его на пропуск.
Простыми словами: сначала берём одноразовый код, потом меняем его на токен.
Аналогия: взять талон и обменять его на пропуск.
Пример:
GET /oauth/authorize?response_type=code&client_id=mobile_app&code_challenge=Y2hhbGxlbmdl&code_challenge_method=S256&state=abc123POST /oauth/tokengrant_type=authorization_codecode=AUTH_CODEcode_verifier=very-secret-string🔎 Как это происходит на практике:
- Клиент генерирует
code_verifierи отправляетcode_challenge. - Сервер отдаёт код авторизации.
- Клиент обменивает код на токен, доказывая владение
code_verifier.
Характеристики:
- ✅ PKCE защищает от перехвата кода
- ✅ подходит для SPA и мобильных
- ✅ параметр
stateзащищает от подмены (CSRF)
Когда использовать: все публичные клиенты без защищённого секрета.
✅ Вывод: PKCE делает выдачу токена безопасной даже без client_secret.
3. Access Token — ключ к API
Назначение: разрешить конкретный доступ к API.
Простыми словами: это временный ключ, который открывает нужные двери.
Аналогия: браслет на фестивале с доступом в определённые зоны.
Простыми словами: это временный ключ, который открывает нужные двери.
Аналогия: браслет на фестивале с доступом в определённые зоны.
Пример:
GET /coursesAuthorization: Bearer eyJhbGciOi...🔎 Как это происходит на практике:
- Клиент хранит токен после входа.
- Отправляет его в заголовке
Authorization. - API проверяет подпись и scope, затем отвечает.
Характеристики:
- ✅ короткий срок жизни (минуты/часы)
- ✅ ограничен scope‑ами
- ✅ может быть JWT или opaque токеном
Когда использовать: каждый запрос к защищённому API.
✅ Вывод: access token — основной ключ для работы с API.
4. Refresh Token — продление сессии
Назначение: получать новый access token без повторного логина.
Простыми словами: это долгий ключ, который обновляет короткий ключ.
Аналогия: абонемент, который продлевает доступ каждый месяц.
Простыми словами: это долгий ключ, который обновляет короткий ключ.
Аналогия: абонемент, который продлевает доступ каждый месяц.
Пример:
POST /oauth/tokengrant_type=refresh_tokenrefresh_token=RT_123🔎 Как это происходит на практике:
- Access token истёк.
- Клиент отправляет refresh token.
- Сервер выдаёт новый access token (и часто новый refresh).
Характеристики:
- ✅ живёт дольше access token
- ✅ должен храниться особенно осторожно
- ✅ ротация refresh token защищает от кражи
Когда использовать: долгие сессии в мобильных и веб‑приложениях.
✅ Вывод: refresh token сохраняет вход, но требует строгой защиты.
5. JWT — формат токена
Назначение: передавать данные токена компактно и с подписью.
Простыми словами: это записка с данными и печатью, чтобы её нельзя подделать.
Аналогия: пропуск с печатью охраны.
Простыми словами: это записка с данными и печатью, чтобы её нельзя подделать.
Аналогия: пропуск с печатью охраны.
Пример:
Header: {"alg":"RS256","typ":"JWT"}Payload: {"sub":"user_42","scope":"courses:read","exp":1712345678}Signature: <подпись>🔎 Как это происходит на практике:
- Сервер подписывает токен своим ключом.
- Клиент отправляет токен в API.
- API проверяет подпись и
exp, затем принимает решение.
Характеристики:
- ✅ подпись подтверждает подлинность
- ✅ токен читаемый, но не шифруется по умолчанию
- ✅ есть срок жизни
exp
Когда использовать: когда нужно быстро проверять токен без БД.
✅ Вывод: JWT удобен, но его надо правильно проверять.
6. Scope — ограничение доступа
Назначение: дать токену только нужные права.
Простыми словами: это список того, что «разрешено».
Аналогия: пропуск только в один зал, а не во всё здание.
Простыми словами: это список того, что «разрешено».
Аналогия: пропуск только в один зал, а не во всё здание.
Пример:
scope=orders:read orders:write🔎 Как это происходит на практике:
- Клиент запрашивает нужные scope.
- Пользователь подтверждает доступ.
- API проверяет scope на каждом запросе.
Характеристики:
- ✅ принцип минимальных прав
- ✅ scope‑ы должны быть документированы
- ✅ каждый endpoint знает, какой scope ему нужен
Когда использовать: при интеграциях и ролях доступа.
✅ Вывод: scope‑ы дают доступ ровно к тому, что нужно.
7. Где хранить токены
Назначение: защитить токены от кражи.
Простыми словами: ключи нельзя класть на витрину.
Аналогия: хранить ключи в сейфе, а не на столе.
Простыми словами: ключи нельзя класть на витрину.
Аналогия: хранить ключи в сейфе, а не на столе.
Пример:
Set-Cookie: access_token=...; HttpOnly; Secure; SameSite=Lax🔎 Как это происходит на практике:
- Сервер ставит HttpOnly cookie.
- Браузер отправляет её автоматически.
- JavaScript не может прочитать токен, XSS не крадёт ключ.
Характеристики:
- ✅ HttpOnly защищает от XSS
- ✅ Secure требует HTTPS
- ✅ SameSite снижает риск CSRF
Когда использовать: веб‑клиенты в браузере.
✅ Вывод: правильное хранение защищает токены от утечек.
Сравнение: OAuth и JWT
| Что сравниваем | OAuth 2.0 | JWT |
|---|---|---|
| Это | протокол доступа | формат токена |
| Задача | выдать доступ | упаковать данные |
| Сам по себе | не токен | может быть токеном |
Сравнение: Access Token vs Refresh Token
| Параметр | Access Token | Refresh Token |
|---|---|---|
| Срок жизни | короткий | долгий |
| Где использовать | каждый запрос | только для обновления |
| Риск кражи | ниже | выше, поэтому важна защита |
Часто спрашивают на собеседованиях
- Чем отличается OAuth от JWT? OAuth — правила, JWT — формат.
- OAuth и аутентификация — одно и то же? Нет, для логина нужен OIDC.
- Почему нужен PKCE? Чтобы код авторизации нельзя было перехватить.
- Access token vs refresh token — в чём разница?
- Что внутри JWT и почему нужно проверять подпись?
- Где хранить токены в браузере и почему не в localStorage?
- Можно ли передавать токен в URL? Нет, он утечёт в логи.
✅ Вывод: эти вопросы — основа интервью по теме.
Типичные ошибки
Ошибка 1: Использовать пароль вместо OAuth
❌ Неправильно: передавать логин/пароль в стороннее приложение.
✅ Правильно: выдавать токен через OAuth.
Почему: пароль нельзя контролировать и отозвать.
✅ Правильно: выдавать токен через OAuth.
Почему: пароль нельзя контролировать и отозвать.
Ошибка 2: Использовать Implicit Flow
❌ Неправильно: отдавать токен прямо в URL.
✅ Правильно: Authorization Code + PKCE.
Почему: токен в URL легко утечь.
✅ Правильно: Authorization Code + PKCE.
Почему: токен в URL легко утечь.
Ошибка 3: Хранить токены в localStorage
❌ Неправильно:
✅ Правильно: HttpOnly cookies или secure storage.
Почему: XSS может украсть токен.
localStorage.setItem("token", ...).✅ Правильно: HttpOnly cookies или secure storage.
Почему: XSS может украсть токен.
Ошибка 4: Не проверять подпись JWT
❌ Неправильно: доверять payload без проверки.
✅ Правильно: проверять подпись и
Почему: без подписи токен можно подделать.
✅ Правильно: проверять подпись и
exp.Почему: без подписи токен можно подделать.
Ошибка 5: Слишком долгий access token
❌ Неправильно: токен живёт неделями.
✅ Правильно: короткий TTL + refresh.
Почему: украденный токен нельзя быстро отозвать.
✅ Правильно: короткий TTL + refresh.
Почему: украденный токен нельзя быстро отозвать.
Ошибка 6: Нет state в OAuth
❌ Неправильно: не передавать
✅ Правильно: хранить
Почему: без этого возможна подмена запроса (CSRF).
state.✅ Правильно: хранить
state и проверять его.Почему: без этого возможна подмена запроса (CSRF).
Ошибка 7: Отправлять токен в query
❌ Неправильно:
✅ Правильно:
Почему: URL попадает в логи и историю.
/api?token=....✅ Правильно:
Authorization: Bearer ....Почему: URL попадает в логи и историю.
Best Practices
- Используйте Authorization Code + PKCE для всех публичных клиентов.
- Делайте access token коротким, refresh token — защищённым.
- Храните токены в HttpOnly cookies или secure storage.
- Всегда проверяйте подпись и срок жизни JWT.
- Документируйте scope‑ы и правила доступа.
- Включайте
stateи CSRF‑защиту. - Используйте HTTPS и отключайте старые протоколы.
Заключение
OAuth 2.0 даёт безопасный доступ без пароля.
JWT делает токен удобным и проверяемым.
Правильное хранение и короткий TTL спасают от краж и дублей.
✅ Вывод: с OAuth и JWT можно строить безопасные и масштабируемые API.