Реалізація авторизації через OpenID Connect в мобільному приложенні
OpenID Connect (OIDC) — OAuth 2.0 плюс стандартизований спосіб отримати інформацію про користувача. OAuth 2.0 вирішує задачу авторизації (доступ до ресурсів), OIDC додає аутентифікацію (хто цей користувач). Різниця принципіальна: OAuth 2.0 access token не гарантує, що в ньому є дані користувача в передбачуваному форматі; OIDC ID token — JWT з фіксованим набором claims (sub, iss, aud, exp, iat мінімум).
ID Token: що з ним робити правильно
Головна помилка — довіряти ID token без верифікації підписи. Бачив проекти, де мобільне приложення парсить payload JWT base64-декодингом та читає sub claim — без перевірки підписи, без перевірки iss та aud. Це еквівалентно довірі будь-якому JWT від кого завгодно.
Правильний flow:
- Отримуємо ID token від Authorization Server.
- Скачуємо JSON Web Key Set (JWKS) по
jwks_uriз discovery document (.well-known/openid-configuration). - Верифікуємо підпис ID token по публічному ключу з JWKS.
- Перевіряємо
iss== очікуваний issuer,audмістить нашclient_id,expне істік,nonceзбігається (захист від replay-атак).
На практиці AppAuth в зв'язці з JWTDecode (iOS) або nimbus-jose-jwt (Android) робить все це. Самостійна реалізація JWKS-верифікації — джерело уязвимостей.
Nonce
Генеруємо nonce криптографічно до початку authorization request, зберігаємо в пам'яті, передаємо в параметрах запиту. Після отримання ID token — перевіряємо, що nonce в token збігається. Якщо сервер повернув token без nonce або з іншим — відклоняємо аутентифікацію. Це захищає від CSRF та replay-атак на мобільному рівні.
Discovery Document та автоконфігурація
OIDC провайдери публікують метадані по .well-known/openid-configuration. AppAuth уміє завантажувати їх автоматично — немає потреби hardcode endpoints:
// iOS — автодискавері
OIDAuthorizationService.discoverConfiguration(forIssuer: issuerURL) { config, error in
guard let config else { return }
// config містить authorizationEndpoint, tokenEndpoint, jwksURL, тощо
}
// Android
AuthorizationServiceConfiguration.fetchFromIssuer(issuerUri) { config, error ->
// використовуємо config для побудови AuthorizationRequest
}
Кешуємо discovery document на розумний термін (година-дві), не завантажуємо при кожній операції.
UserInfo endpoint
Після отримання access token можна запросити userinfo_endpoint для отримання додаткових claims (email, name, picture, phone_number). Claims у ID token намисно мінімальні — OIDC Core не гарантує їхню наявність без явного запиту через scope (profile, email, phone, address).
Важливо: userinfo endpoint захищений access token. Якщо access token істік — треба обновити його через refresh token до запиту userinfo. Робимо це прозоро через interceptor/middleware в HTTP-клієнті.
Logout: часто забувають
OIDC визначає три варіанти завершення сесії:
-
RP-Initiated Logout (rp = Relying Party, ваше приложення): редиректимо на
end_session_endpoint. - Front-Channel Logout: сервер пингує відомих клієнтів через iframe (не застосовується для native приложень).
-
Back-Channel Logout: сервер відправляє POST-запит на зареєстрований
backchannel_logout_uriвашого сервера.
Для мобільних приложень працює тільки RP-Initiated. Відкриваємо end_session_endpoint в браузері (ASWebAuthenticationSession/Custom Tabs), передаємо id_token_hint та post_logout_redirect_uri. Без id_token_hint деякі провайдери (Keycloak, Auth0) не завершать сесію на сервері — користувач вийде з приложення, але SSO-сесія в браузері залишиться активною.
Інтеграція з корпоративними IdP
Keycloak, Azure AD, Okta, Ping Identity — всі підтримують OIDC. Основні різниці: формат claims (Azure AD використовує oid замість sub як стабільний ідентифікатор користувача), додаткові non-standard claims (ролі, групи), особливості refresh token rotation.
Azure AD B2C додає User Flows — кожен flow має свій issuer, що ломає стандартний JWKS-кеш. Треба або динамічно резолвити issuer з ID token, або налаштувати статичний список trusted issuers.
Терміни
Один OIDC провайдер зі стандартною конфігурацією — 5–8 робочих днів (включно з тестами та налаштуванням redirect). Корпоративний IdP з нестандартними claims та B2C user flows — 10–15 днів з координацією з командою IdP.







