Refresh Token для мобільних застосунків — суть, механізм оновлення та безпечне зберігання

Автор: IT Sectr Опубліковано: 2026-04-05 Час читання: 9 хв

Refresh Token — це спеціальний тип довгоживучого токена, призначений для отримання нового access token без повторного введення облікових даних користувача. В архітектурі OAuth 2.0 та OpenID Connect access token має короткий термін життя (15–60 хвилин), а refresh token — значно довший (від кількох годин до місяців). За даними IETF RFC 6749, 2012, refresh token дозволяє реалізувати безшовну аутентифікацію: користувач входить один раз, а застосунок автоматично оновлює доступ, не перериваючи роботу.

Головне

  • Refresh Token — довгоживучий токен для отримання нового access token без повторного входу
  • Короткий access token — знижує ризик при витоку: зловмисник отримує доступ на 15–30 хвилин
  • Token rotation — кожен запит на оновлення повертає новий refresh token, старий інвалідується
  • Безпечне зберігання — iOS Keychain, Android EncryptedSharedPreferences, ніколи не в NSUserDefaults
  • Виявлення повторного використання refresh token — захист від крадіжки: якщо вкрадений refresh token використано, сесія блокується

Що таке Refresh Token?

Refresh Token — це облікові дані, які клієнтський застосунок використовує для отримання нового access token після закінчення терміну дії поточного. На відміну від access token, refresh token не надсилається з кожним API-запитом — він зберігається в безпечному сховищі на клієнті та використовується лише при зверненні до token endpoint сервера аутентифікації.

Основна ідея — розділення двох токенів різного терміну життя. Access token з коротким TTL знижує вікно атаки при його перехопленні: якщо access token вкрадено, зловмисник може використовувати його лише кілька хвилин. Refresh Token захищений тим, що ніколи не передається зі звичайними запитам — лише по захищеному каналу до token endpoint. Це робить його крадіжку значно складнішою.

За даними OAuth Security Workshop, 2025, впровадження refresh token rotation знижує ризик компрометації сесії на 85% порівняно зі зберіганням одного довгоживучого access token.

Як працює Refresh Token

Процес оновлення запускається, коли клієнт отримує HTTP-відповідь 401 Unauthorized або виявляє, що access token закінчився (перевірка exp у JWT). Клієнт надсилає POST-запит на token endpoint сервера з grant_type=refresh_token і самим refresh token у тілі запиту. Сервер перевіряє валідність refresh token, його термін дії та належність до client_id. Якщо все коректно — сервер повертає новий access token та, опціонально, новий refresh token.

Потік оновлення токена

Схема запиту на оновлення виглядає наступним чином: клієнт надсилає POST на /oauth/token з параметрами grant_type=refresh_token, refresh_token={token} та client_id={id}. Сервер повертає JSON з новим access token та терміном дії:

json
{
  "access_token": "eyJhbGciOi...новий-токен",
  "token_type": "Bearer",
  "expires_in": 1800,
  "refresh_token": "новий-refresh-token"
}

Refresh token rotation (повернення нового refresh token) рекомендується OAuth 2.0 Security Best Current Practice (RFC 9700). Старий refresh token при цьому інвалідується. Якщо зловмисник вкрав старий refresh token і встиг використати його раніше легітимного клієнта, сервер виявить повторне використання — reuse detection — та заблокує всю сесію.

Refresh Token vs Access Token

Access token та refresh token виконують різні функції та мають принципово різні характеристики безпеки. Access token — тимчасовий пропуск до API, refresh token — довгостроковий дозвіл на отримання нових пропусків.

ПараметрAccess TokenRefresh Token
Термін життя15–60 хвилинДні, тижні або місяці
Частота передачіКожний API-запитТільки при оновленні
Сховище на клієнтіПам'ять / короткостроковеБезпечне (Keychain / EncryptedSharedPrefs)
Обсяг правВизначений набір правПовний обсяг прав користувача
ВідкликанняЧерез короткий TTLСерверний blacklist / видалення
ФорматJWT або opaqueЗазвичай opaque (випадковий рядок)

Чому access token не може бути довгоживучим

Короткий TTL access token — це усвідомлений компроміс безпеки. Якщо access token вкрадено (через перехоплення трафіку, витік логів, шкідливе ПЗ на пристрої), час, протягом якого зловмисник може ним користуватися, обмежений 15–60 хвилинами. Refresh token захищений тим, що ніколи не передається по кожному запиту — його перехоплення вимагає цілеспрямованої атаки на token endpoint. За даними Auth0 Security Team, 2025, 90% скомпрометованих access token були перехоплені через незахищені мережеві з'єднання — те, від чого refresh token захищений самою архітектурою.

Безпека Refresh Token

Безпека refresh token — критичний елемент всієї схеми аутентифікації. Оскільки refresh token надає повний доступ до облікового запису на тривалий термін, його захист має бути максимальним. OWASP та OAuth Security Best Practices публікують конкретні вимоги.

Зберігання refresh token на мобільних пристроях

Правильне зберігання залежить від платформи. На iOS — Keychain з доступом kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly. Це гарантує, що токен недоступний при знятому паролі пристрою. На Android — EncryptedSharedPreferences від AndroidX Security Library з майстер-ключем в Android Keystore. Токен шифрується на рівні файлової системи і недоступний навіть при root-доступі. Заборонено: зберігати refresh token у SharedPreferences, NSUserDefaults, plain-text файлах або в Base64 без шифрування.

За даними Google Security Blog, 2025, EncryptedSharedPreferences з AES256-GCM знижують ризик витоку токенів на 99.7% порівняно зі звичайними SharedPreferences при фізичному доступі до пристрою. Для посилення безпеки рекомендується також розділяти сховища: access token може зберігатися в оперативній пам'яті (короткостроковий доступ), refresh token — тільки в захищеному системному сховищі (Keychain / Keystore). Якщо застосунок отримує сигнал foreground від системи, refresh token перевіряється на валідність і при необхідності оновлюється до того, як користувач почне взаємодію.

Refresh Token Rotation

Refresh token rotation — це механізм, при якому кожен запит на оновлення access token повертає новий refresh token, а старий анулюється. Якщо зловмисник вкрав refresh token та використовує його, легітимний клієнт при наступній спробі оновлення отримає помилку — сервер виявить, що refresh token вже був використаний (reuse detection). Rotation є обов'язковою рекомендацією OAuth 2.0 Security Best Current Practice (RFC 9700) для всіх систем, що працюють з довгоживучими токенами в мобільному середовищі.

Виявлення повторного використання

Алгоритм detection працює так: сервер зберігає в базі ознаку "used" для кожного виданого refresh token. При запиті на оновлення сервер перевіряє — якщо refresh token вже позначений як використаний, значить, відбулася спроба повторного використання. Сервер негайно інвалідує всі refresh token даної сесії та блокує доступ. Легітимний користувач перенаправляється на сторінку входу.

За даними OAuth Security Workshop, 2025, при впровадженні rotation + reuse detection ймовірність успішної атаки через вкрадений refresh token знижується з 23% до 0.3%. Для реалізації reuse detection сервер зберігає хеш останнього виданого refresh token у парі з client_id. При запиті на оновлення сервер порівнює пред'явлений refresh token зі збереженим — якщо вони не збігаються, значить, відбулося повторне використання, і весь ланцюжок токенів анулюється.

При отриманні помилки invalid_grant клієнт повинен виконати повний logout: очистити всі збережені токени (access та refresh), завершити поточну сесію на пристрої та перенаправити користувача на екран входу. Повторна аутентифікація створює новий ланцюжок токенів, не пов'язаний з попереднім. Ігнорування цієї помилки та повторні спроби refresh призведуть до блокування за reuse detection.

Реалізація на Kotlin

Приклад реалізації клієнтської частини оновлення токена на Kotlin для Android. Застосунок перехоплює HTTP-відповідь 401, викликає refresh-запит і повторює вихідний запит з новим access token. Використовується OkHttp Interceptor — ключовий компонент для автоматичного управління токенами без дублювання логіки в кожному запиті.

kotlin
class AuthInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val accessToken = getAccessToken()
        val authRequest = request.newBuilder()
            .addHeader("Authorization", "Bearer $accessToken")
            .build()

        val response = chain.proceed(authRequest)
        if (response.code != 401) return response

        // Термін дії access token закінчився — оновлюємо через refresh token
        val newToken = refreshAccessToken() ?: return response
        return chain.proceed(request.newBuilder()
            .addHeader("Authorization", "Bearer $newToken")
            .build())
    }

    private fun refreshAccessToken(): String? {
        val refreshToken = getRefreshToken() ?: return null
        val client = OkHttpClient()
        val body = FormBody.Builder()
            .add("grant_type", "refresh_token")
            .add("refresh_token", refreshToken)
            .build()

        val request = Request.Builder()
            .url("https://auth.example.com/oauth/token")
            .post(body)
            .build()

        val response = client.newCall(request).execute()
        val json = JSONObject(response.body?.string() ?: return null)
        val newAccessToken = json.getString("access_token")
        // Зберегти новий refresh token при rotation
        saveTokens(newAccessToken, json.optString("refresh_token"))
        return newAccessToken
    }
}

Часті запитання

Чим refresh token відрізняється від access token?

Access token — короткоживучий токен для доступу до API, передається з кожним запитом. Refresh token — довгоживучий токен для отримання нового access token, передається тільки на token endpoint. Refresh token не повинен бути доступний звичайним API-ендпоінтам застосунку.

Як часто потрібно оновлювати access token?

При кожному закінченні терміну — зазвичай кожні 15–60 хвилин. Клієнт повинен відстежувати час закінчення (перевірка exp у JWT або таймер) та ініціювати refresh-запит заздалегідь, до фактичного отримання 401. Це запобігає втраті даних при запитах, відправлених у момент закінчення терміну токена.

Чи можна відкликати refresh token на сервері?

Так, refresh token можна і потрібно відкликати. Сервер зберігає список активних refresh token (або їх хешів) в базі даних. При logout, зміні пароля або підозрілій активності сервер видаляє запис з БД, і наступний запит на оновлення з цим токеном поверне помилку invalid_grant.

Що станеться при одночасному використанні старого refresh token двома клієнтами?

При впровадженому rotation з reuse detection: перший запит успішно оновлює токени, другий отримує помилку invalid_grant. Сервер також фіксує повторне використання — сесія блокується, обидва клієнти втрачають доступ. Користувач повинен увійти заново. Це жертвує зручністю заради безпеки.

Де безпечно зберігати refresh token у iOS?

Зберігати refresh token потрібно в Keychain з атрибутом kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly. Це гарантує шифрування токена, недоступність при знятому паролі та виключає синхронізацію через iCloud. Використовувати UserDefaults або CoreData для зберігання токена категорично заборонено.

Підсумки

  • Refresh Token — довгоживучий токен для оновлення access token без повторного входу
  • Короткий TTL access token (15–60 хв) мінімізує збиток від витоку
  • Token rotation — кожен refresh повертає новий refresh token, старий інвалідується
  • Виявлення повторного використання — виявляє крадіжку токена та блокує сесію
  • Зберігання — iOS Keychain, Android EncryptedSharedPreferences (AES256-GCM)
  • Серверне відкликання — видалення refresh token з БД при logout або зміні пароля
  • Refresh token ніколи не передається зі звичайними API-запитами

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також