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 символов, only 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 — сервер авторизации должен строгo валидировать соответствие зарегистрированному 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 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также