OAuth 2.0 — це промисловий протокол авторизації, який надає стороннім додаткам обмежений доступ до ресурсів користувача без передачі його облікових даних. Протокол став стандартом де-факто для делегованої авторизації у веб і мобільних додатках, використовуючись такими платформами як Google, Facebook, Apple і GitHub. Згідно з IETF RFC 6749 (2025), OAuth 2.0 застосовується в більш ніж 85% усіх API-інтеграцій, що вимагають делегованого доступу до даних.
Головне
OAuth 2.0 — це протокол авторизації, визначений в IETF RFC 6749, який дозволяє стороннім додаткам отримувати обмежений доступ до ресурсів користувача без розкриття його логіна та пароля. Протокол вирішує фундаментальну проблему парольної моделі: додаток, якому ви довірили пароль, отримує необмежений доступ до всіх даних облікового запису. OAuth 2.0 замінює цей підхід видачею тимчасового токена з явно обмеженою областю доступу (scope).
Архітектура OAuth 2.0 — делегована авторизація. Користувач (Resource Owner) авторизує додаток (Client) на доступ до своїх даних, що зберігаються на сервері ресурсів (Resource Server), через посередника — сервер авторизації (Authorization Server). Сервер авторизації випускає Access Token — криптографічний рядок, який додаток пред'являє серверу ресурсів для доступу до даних. Важлива відмінність OAuth 2.0 від SAML і OpenID Connect: OAuth 2.0 вирішує задачу авторизації (що дозволено), а не аутентифікації (хто користувач). Для аутентифікації поверх OAuth 2.0 будується протокол OpenID Connect (OIDC).
Протокол підтримується всіма великими платформами. Google використовує OAuth 2.0 для доступу до Google APIs (Gmail, Drive, Calendar), Facebook — для Graph API, Apple — для Sign in with Apple (ASAuthorizationAppleIDProvider), GitHub — для доступу до репозиторіїв. У контексті мобільної розробки OAuth 2.0 — стандартний механізм інтеграції сторонніх сервісів: вхід через соціальні мережі, доступ до хмарних сховищ, публікація контенту від імені користувача.
Протокол OAuth 2.0 визначає чотири ролі, взаємодія яких становить повний цикл авторизації. Розуміння кожної ролі необхідне для коректної реалізації протоколу в мобільному додатку.
| Роль | Опис | Приклад |
|---|---|---|
| Resource Owner | Власник даних — користувач, який дозволяє доступ до своїх ресурсів | Користувач додатка, який натискає «Увійти через Google» |
| Client | Додаток, що запитує доступ до ресурсів від імені власника | Мобільний додаток, якому потрібен доступ до Google Drive |
| Authorization Server | Сервер, що випускає токени після аутентифікації та авторизації | accounts.google.com — сервер авторизації Google |
| Resource Server | API, що надає доступ до захищених ресурсів за токеном | www.googleapis.com — сервер ресурсів Google Drive API |
Ключові сутності протоколу — Access Token, Refresh Token і Authorization Code. Access Token — короткоживучий токен (зазвичай 15–60 хвилин), що пред'являється серверу ресурсів при кожному запиті даних. Refresh Token — довгоживучий токен (дні або тижні), що використовується для отримання нового Access Token без повторного входу користувача. Authorization Code — тимчасовий код, що видається після авторизації користувача та обмінюється на Access Token і Refresh Token.
OAuth 2.0 визначає кілька Grant Types — сценаріїв отримання токена, кожен з яких призначений для певного типу клієнта та контексту безпеки. Вибір правильного Grant Type — критичне архітектурне рішення при проектуванні авторизації в мобільному додатку.
Основні Grant Types: Authorization Code (найбезпечніший для мобільних і веб-додатків з серверним компонентом), Authorization Code з PKCE (Proof Key for Code Exchange — для мобільних і SPA-додатків без серверного бекенду), Client Credentials (для сервер-серверної аутентифікації без участі користувача), Resource Owner Password Credentials (застарілий — передача пароля безпосередньо). PKCE є обов'язковим розширенням для публічних клієнтів (мобільні додатки, SPA) згідно з рекомендаціями OAuth Security BCP (RFC 9700).
Authorization Code Flow з PKCE — це рекомендована конфігурація OAuth 2.0 для нативних мобільних додатків. PKCE (Proof Key for Code Exchange) додає додатковий рівень захисту, що запобігає атаці перехоплення authorization code (authorization code interception attack). Протокол описаний в IETF RFC 7636.
Послідовність кроків: (1) клієнт генерує випадковий code_verifier (рядок 43–128 символів, тільки unreserved characters), (2) клієнт обчислює code_challenge = SHA-256(code_verifier), (3) клієнт відкриває браузер для авторизації користувача на Authorization Server, передаючи code_challenge, (4) після успішної авторизації сервер повертає authorization code в додаток через кастомний URI scheme (app deep link), (5) клієнт відправляє серверу authorization code + code_verifier, (6) сервер перевіряє SHA-256(code_verifier) === code_challenge і видає Access Token + Refresh Token.
Перевага PKCE — навіть якщо зловмисник перехопить authorization code в URI-схемі, він не зможе обміняти його на токен без code_verifier, який відомий тільки легітимному клієнту. У мобільних додатках для відкриття браузера слід використовувати Chrome Custom Tabs (Android) або ASWebAuthenticationSession (iOS) — це гарантує, що системний браузер не має доступу до code_verifier з пам'яті додатка.
AppAuth — це еталонна реалізація OAuth 2.0 і OpenID Connect для нативних додатків, рекомендована IETF. Бібліотека підтримує PKCE, Chrome Custom Tabs, кастомні URI-схеми для повернення authorization code і автоматичне оновлення токенів. AppAuth для Android доступний через dependency `net.openid:appauth:0.11.1`.
val serviceConfig = AuthorizationServiceConfiguration.fromUrl(
Uri.parse("https://accounts.google.com/.well-known/openid-configuration")
)
val request = AuthorizationRequest.Builder(
serviceConfig,
"CLIENT_ID.apps.googleusercontent.com",
ResponseTypeValues.CODE,
Uri.parse("com.example.app:/oauth2callback")
)
.setScope("openid profile email")
.setCodeVerifier(
CodeVerifierUtil.generateRandomCodeVerifier()
)
.build()
val authService = AuthorizationService(context)
val intent = authService.getAuthorizationRequestIntent(request)
// Запуск Chrome Custom Tab для авторизації
startActivityForResult(intent, REQUEST_CODE_AUTH)
Після отримання authorization code (onActivityResult) додаток обмінює його на Access Token і Refresh Token через TokenRequest. Токени зберігаються в SharedPreferences з шифруванням через EncryptedSharedPreferences (Android Security Crypto). Refresh Token повинен зберігатися в KeyStore — апаратному сховищі ключів, недоступному для читання іншими додатками. При кожному закінченні терміну дії Access Token додаток використовує Refresh Token для отримання нового — користувачу не потрібно повторно авторизуватися.
// Обмін authorization code на токени
val data = intent?.data ?: return
val resp = AuthorizationResponse.fromIntent(data)
val exchangeReq = resp?.createTokenExchangeRequest()
?: return
authService.performTokenRequest(
exchangeReq,
ClientAuthentication.none()
) { tokenResp, ex ->
if (tokenResp != null) {
// Access Token і Refresh Token отримані
val accessToken = tokenResp.accessToken
val refreshToken = tokenResp.refreshToken
// Зберегти в EncryptedSharedPreferences
saveTokens(accessToken, refreshToken)
}
}
Наведений код демонструє повний цикл OAuth 2.0 з PKCE: створення конфігурації сервера через OpenID Connect Discovery, генерація запиту авторизації з code_verifier, запуск Chrome Custom Tab, прийом authorization code через кастомну URI-схему та обмін коду на токени через Token Request. Важливо обробляти закінчення терміну дії Access Token: при HTTP-відповіді 401 від Resource Server додаток повинен використовувати Refresh Token для отримання нового Access Token і повторно виконати запит.
OAuth 2.0 — складний протокол з безліччю точок атаки. IETF Security BCP (RFC 9700) описує більш ніж 20 класів вразливостей OAuth 2.0. Для мобільних додатків найбільш критичні: перехоплення authorization code через кастомні URI-схеми, CSRF-атаки на callback-ендпоїнти, крадіжка Refresh Token з небезпечного сховища та підміна клієнта через інтент-перехоплення.
Захист від цих атак включає обов'язкові заходи: (1) PKCE з S256 code_challenge — запобігає перехопленню authorization code навіть при перехопленні URI-схеми; (2) використання nonce або state parameter для запобігання CSRF — сервер перевіряє, що authorization code відповідає початковому запиту; (3) зберігання Refresh Token тільки в KeyStore (Android) або Keychain (iOS) — ні в SharedPreferences, ні в UserDefaults; (4) використання TLS з Certificate Pinning для захисту MITM на транспортному рівні; (5) перевірка redirect_uri — сервер авторизації повинен строго валідувати відповідність зареєстрованому URI.
Додаткові рекомендації від IETF: мобільним додаткам слід використовувати AppAuth або аналогічні бібліотеки, що пройшли аудит безпеки; не покладатися на WebView для OAuth (WebView не ізолює дані від основного додатка); реалізувати автоматичну ротацію Refresh Token (один Refresh Token може бути використаний одноразово); додавати Certificate Pinning через TrustManager для Android і URLSession для iOS. OpenID Connect Discovery (well-known endpoint) допомагає автоматично визначити коректні ендпоїнти сервера авторизації та уникнути редиректів на фішингові сторінки.
Часті запитання
OAuth 2.0 — протокол авторизації (що дозволено робити?), а OpenID Connect (OIDC) — протокол аутентифікації (хто користувач?). OIDC будується поверх OAuth 2.0 і додає ID Token — JWT-токен, що містить інформацію про особистість користувача. OAuth 2.0 дає Access Token, OIDC доповнює його ID Token і UserInfo endpoint для отримання профілю користувача.
Bearer Token — це Access Token, який пред'являється в HTTP-заголовку Authorization: Bearer. Його небезпека в тому, що будь-хто, хто володіє токеном, може отримати доступ до ресурсу — токен не прив'язаний до клієнта. Тому Bearer Token повинен передаватися тільки через TLS (HTTPS), мати короткий термін життя (15–60 хвилин) і ніколи не зберігатися в логах або URL-параметрах.
Мобільні додатки — публічні клієнти, що не мають client_secret (секрет не може бути захищений в APK/IPA). Без PKCE зловмисник може перехопити authorization code через кастомну URI-схему (наприклад, malformed://callback?code=ABC) і обміняти його на токен. PKCE додає code_verifier, відомий тільки додатку, роблячи перехоплений код марним.
Типовий Access Token живе 15–60 хвилин (налаштовується сервером авторизації). При кожному HTTP-запиті до Resource Server перевіряється відповідь: якщо код 401, додаток викликає Refresh Token Flow для отримання нового Access Token. Refresh Token живе від 24 годин до кількох місяців, залежно від політики безпеки провайдера. При зміні Refresh Token старий анулюється.
Ні — IETF Security BCP (RFC 9700) забороняє WebView для OAuth 2.0 в мобільних додатках. WebView не ізолює куки та дані від основного додатка, що дозволяє додатку перехопити credentials користувача. Замість WebView використовуйте Chrome Custom Tabs (Android) або ASWebAuthenticationSession (iOS) — системні браузерні компоненти, ізольовані від додатка.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також