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 reuse detection — заштита од крађе: ако је украдени 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...nowy-token",
  "token_type": "Bearer",
  "expires_in": 1800,
  "refresh_token": "nowy-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)
ScopeОдређени скуп праваПун обим права корисника
ОпзивКроз кратак 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) за све системе који раде са дуговечним токенима у мобилном окружењу.

Reuse Detection

Алгоритам detection ради овако: сервер чува у бази ознаку „used” за сваки издати refresh token. При захтеву за освежавање сервер проверава — ако је 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 клијент треба да изврши потпуни одјаву: обрише све сачуване токене (access и refresh), заврши тренутну сесију на уређају и преусмери корисника на екран за пријаву. Поновна аутентификација ствара нови ланац токена, који није повезан са претходним. Игнорисање ове грешке и поновљени покушаји освежавања довешче до блокирања путем reuse detection.

Имплементација у Kotlin

Примјер имплементације клијентског дијела освежавања токена у Kotlin-у за Android. Апликација пресрета HTTP одговор 401, позива захтев за освежавање и понавља оригинални захтев са новим 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 или тајмер) и покрене захтев за освежавање унапред, пре него што заиста добије 401. То спречава губитак података при захтевима послатим у тренутку истека токена.

Може ли се опзвати refresh token на серверу?

Да, refresh token се може и треба опзвати. Сервер чува листу активних refresh token (или њихових хешева) у бази података. При одјави, промени лозинке или сумњивијој активности сервер брише унос из базе података, и следећи захтев за освежавање са овим токеном враћа грешку 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 token, стари се инвалидира
  • Reuse detection — открива крађу токена и блокира сесију
  • Чување — iOS Keychain, Android EncryptedSharedPreferences (AES256-GCM)
  • Серверски опзив — брисање refresh token из базе података при одјави или промени лозинке
  • Refresh token се никада не преноси са обичним API захтевима

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође