Refresh Token voor mobiele apps — essentie, vernieuwingsmechanisme en veilige opslag

Auteur: IT Sectr Gepubliceerd: 2026-04-05 Leestijd: 9 min

Refresh Token — is een speciaal type langlevende token bedoeld om een nieuwe access token te verkrijgen zonder dat de gebruiker opnieuw zijn inloggegevens hoeft in te voeren. In de architectuur van OAuth 2.0 en OpenID Connect heeft een access token een korte levensduur (15–60 minuten) en een refresh token een aanzienlijk langere (van enkele uren tot maanden). Volgens IETF RFC 6749, 2012 maakt een refresh token naadloze authenticatie mogelijk: de gebruiker logt een keer in en de applicatie vernieuwt automatisch de toegang zonder het werk te onderbreken.

Belangrijkste punten

  • Refresh Token — langlevende token voor het verkrijgen van een nieuwe access token zonder opnieuw inloggen
  • Korte access token — verlaagt het risico bij lekkage: een aanvaller krijgt slechts 15–30 minuten toegang
  • Token rotation — elke vernieuwingsaanvraag retourneert een nieuwe refresh token, de oude wordt ongeldig gemaakt
  • Veilige opslag — iOS Keychain, Android EncryptedSharedPreferences, nooit in NSUserDefaults
  • Refresh token reuse detection — bescherming tegen diefstal: als de gestolen refresh token wordt gebruikt, wordt de sessie geblokkeerd

Wat is een Refresh Token?

Refresh Token — is een credential die de clientapplicatie gebruikt om een nieuwe access token te verkrijgen nadat de huidige is verlopen. In tegenstelling tot een access token wordt een refresh token niet met elk API-verzoek meegestuurd — het wordt opgeslagen in een veilige opslag op de client en alleen gebruikt bij het benaderen van het token endpoint van de authenticatieserver.

Het hoofdidee is het scheiden van twee tokens met verschillende levensduur. Een access token met een korte TTL verkleint het aanvalsvenster bij onderschepping: als een access token wordt gestolen, kan de aanvaller het slechts enkele minuten gebruiken. Refresh token wordt beschermd doordat het nooit met gewone verzoeken wordt meegestuurd — alleen via een beveiligd kanaal naar het token endpoint. Dit maakt diefstal aanzienlijk moeilijker.

Volgens OAuth Security Workshop, 2025 vermindert de implementatie van refresh token met rotation het risico op sessiecompromittering met 85% in vergelijking met het opslaan van een enkele langlevende access token.

Hoe werkt een Refresh Token

Het vernieuwingsproces wordt gestart wanneer de client een HTTP 401 Unauthorized-antwoord ontvangt of detecteert dat de access token is verlopen (controle van exp in JWT). De client stuurt een POST-verzoek naar het token endpoint van de server met grant_type=refresh_token en de refresh token zelf in de aanvraagbody. De server controleert de geldigheid van de refresh token, de vervaldatum en de toewijzing aan client_id. Als alles correct is — retourneert de server een nieuwe access token en optioneel een nieuwe refresh token.

Tokenvernieuwingsstroom

Het schema van de vernieuwingsaanvraag ziet er als volgt uit: de client stuurt een POST naar /oauth/token met parameters grant_type=refresh_token, refresh_token={token} en client_id={id}. De server retourneert een JSON met de nieuwe access token en vervaldatum:

json
{
  "access_token": "eyJhbGciOi...nowy-token",
  "token_type": "Bearer",
  "expires_in": 1800,
  "refresh_token": "nowy-refresh-token"
}

Refresh token rotation (het retourneren van een nieuwe refresh token) wordt aanbevolen door OAuth 2.0 Security Best Current Practice (RFC 9700). De oude refresh token wordt hierbij ongeldig gemaakt. Als een aanvaller de oude refresh token heeft gestolen en deze vóór de legitieme client heeft kunnen gebruiken, detecteert de server het herhaalde gebruik — reuse detection — en blokkeert de hele sessie.

Refresh Token vs Access Token

Access token en refresh token vervullen verschillende functies en hebben fundamenteel verschillende beveiligingskenmerken. Access token is een tijdelijke toegangspas voor de API, refresh token is een langdurige autorisatie om nieuwe passen te verkrijgen.

ParameterAccess TokenRefresh Token
Levensduur15–60 minutenDagen, weken of maanden
Frequentie van verzendingElk API-verzoekAlleen bij vernieuwing
Opslag op clientGeheugen / korte termijnVeilig (Keychain / EncryptedSharedPrefs)
ScopeSpecifieke rechten setVolledige rechtenomvang van de gebruiker
IntrekkingVia korte TTLServer blacklist / verwijdering
FormaatJWT of opaqueMeestal opaque (willekeurige string)

Waarom een access token niet langlevend kan zijn

Korte TTL van access token — is een bewust beveiligingscompromis. Als een access token wordt gestolen (via verkeersonderschepping, loglekken, kwaadaardige software op het apparaat), is de tijd waarin de aanvaller het kan gebruiken beperkt tot 15–60 minuten. Refresh token wordt beschermd doordat het nooit bij elk verzoek wordt meegestuurd — onderschepping ervan vereist een gerichte aanval op het token endpoint. Volgens Auth0 Security Team, 2025 werd 90% van de gecompromitteerde access tokens onderschept via onbeveiligde netwerkverbindingen — precies waar refresh token door zijn architectuur tegen wordt beschermd.

Beveiliging van Refresh Token

Beveiliging van refresh token — een kritiek element van het hele authenticatieschema. Omdat refresh token volledige toegang tot het account biedt voor een lange periode, moet de bescherming ervan maximaal zijn. OWASP en OAuth Security Best Practices publiceren specifieke vereisten.

Opslag van refresh token op mobiele apparaten

Correcte opslag hangt af van het platform. Op iOS — Keychain met toegang kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly. Dit garandeert dat de token niet beschikbaar is wanneer het apparaatwachtwoord is verwijderd. Op Android — EncryptedSharedPreferences van AndroidX Security Library met de master-sleutel in Android Keystore. De token wordt versleuteld op bestandssysteemniveau en is zelfs met root-toegang niet beschikbaar. Verboden: refresh token opslaan in SharedPreferences, NSUserDefaults, plain-text bestanden of in Base64 zonder versleuteling.

Volgens Google Security Blog, 2025 verminderen EncryptedSharedPreferences met AES256-GCM het risico op tokenlekkage met 99.7% in vergelijking met gewone SharedPreferences bij fysieke toegang tot het apparaat. Voor extra beveiliging wordt ook aanbevolen om de opslagplaatsen te scheiden: access token kan in het werkgeheugen worden opgeslagen (korte termijn toegang), refresh token — alleen in de beveiligde systeemopslag (Keychain / Keystore). Als de applicatie een foreground-signaal van het systeem ontvangt, wordt de refresh token gecontroleerd op geldigheid en indien nodig vernieuwd voordat de gebruiker interactie start.

Refresh Token Rotation

Refresh token rotation — is een mechanisme waarbij elk verzoek om een access token te vernieuwen een nieuwe refresh token retourneert en de oude wordt geannuleerd. Als een aanvaller een refresh token heeft gestolen en gebruikt, krijgt de legitieme client bij de volgende vernieuwingspoging een foutmelding — de server detecteert dat de refresh token al is gebruikt (reuse detection). Rotation is een verplichte aanbeveling van OAuth 2.0 Security Best Current Practice (RFC 9700) voor alle systemen die met langlevende tokens in een mobiele omgeving werken.

Reuse Detection

Het detectie-algoritme werkt als volgt: de server slaat in de database een „used”-markering op voor elke uitgegeven refresh token. Bij een vernieuwingsverzoek controleert de server — als de refresh token al als gebruikt is gemarkeerd, betekent dit een poging tot herhaald gebruik. De server maakt onmiddellijk alle refresh tokens van deze sessie ongeldig en blokkeert de toegang. De legitieme gebruiker wordt doorgestuurd naar de inlogpagina. Dit voorkomt aanvallen met diefstal van refresh tokens: de aanvaller krijgt toegang, maar de sessie wordt onmiddellijk na detectie geblokkeerd.

Volgens OAuth Security Workshop, 2025 daalt bij implementatie van rotation + reuse detection de kans op een succesvolle aanval via een gestolen refresh token van 23% naar 0.3%. Voor de implementatie van reuse detection slaat de server de hash van de laatst uitgegeven refresh token op samen met client_id. Bij een vernieuwingsverzoek vergelijkt de server de aangeboden refresh token met de opgeslagen — als ze niet overeenkomen, is er sprake van herhaald gebruik en wordt de hele token-keten geannuleerd.

Bij ontvangst van de foutmelding invalid_grant moet de client een volledige logout uitvoeren: alle opgeslagen tokens (access en refresh) wissen, de huidige sessie op het apparaat beëindigen en de gebruiker doorsturen naar het inlogscherm. Opnieuw authenticeren creëert een nieuwe token-keten die niet is gekoppeld aan de vorige. Het negeren van deze fout en herhaalde vernieuwingspogingen zullen leiden tot blokkering via reuse detection.

Implementatie in Kotlin

Voorbeeld van implementatie van het clientgedeelte voor tokenvernieuwing in Kotlin voor Android. De applicatie onderschept het HTTP 401-antwoord, roept een vernieuwingsverzoek aan en herhaalt het oorspronkelijke verzoek met de nieuwe access token. Er wordt OkHttp Interceptor gebruikt — een belangrijk onderdeel voor automatisch tokenbeheer zonder het dupliceren van logica in elk verzoek.

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 verlopen — vernieuwen via 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")
        // Nieuwe refresh token opslaan bij rotation
        saveTokens(newAccessToken, json.optString("refresh_token"))
        return newAccessToken
    }
}

Veelgestelde vragen

Waarin verschilt een refresh token van een access token?

Access token — kortlevende token voor toegang tot de API, wordt met elk verzoek meegestuurd. Refresh token — langlevende token voor het verkrijgen van een nieuwe access token, wordt alleen naar het token endpoint gestuurd. Refresh token mag niet beschikbaar zijn voor de gewone API-eindpunten van de applicatie.

Hoe vaak moet een access token worden vernieuwd?

Bij elke vervaldatum — meestal elke 15–60 minuten. De client moet de vervaltijd bijhouden (controle van exp in JWT of een timer) en de vernieuwingsaanvraag vooraf starten, voordat daadwerkelijk een 401 wordt ontvangen. Dit voorkomt gegevensverlies bij verzoeken die op het moment van tokenverval zijn verzonden.

Kan een refresh token op de server worden ingetrokken?

Ja, een refresh token kan en moet worden ingetrokken. De server bewaart een lijst van actieve refresh tokens (of hun hashes) in de database. Bij logout, wachtwoordwijziging of verdachte activiteit verwijdert de server het record uit de database en de volgende vernieuwingsaanvraag met deze token retourneert de foutmelding invalid_grant.

Wat gebeurt er bij gelijktijdig gebruik van de oude refresh token door twee clients?

Bij geïmplementeerde rotation met reuse detection: het eerste verzoek vernieuwt de tokens succesvol, het tweede krijgt de foutmelding invalid_grant. De server registreert ook het herhaalde gebruik — de sessie wordt geblokkeerd, beide clients verliezen de toegang. De gebruiker moet opnieuw inloggen. Dit is het opofferen van gemak voor veiligheid.

Waar moet ik een refresh token veilig opslaan in iOS?

Refresh token moet worden opgeslagen in de Keychain met het attribuut kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly. Dit garandeert versleuteling van de token, onbeschikbaarheid bij het verwijderen van het wachtwoord en sluit synchronisatie via iCloud uit. Het gebruik van UserDefaults of CoreData voor het opslaan van de token is ten strengste verboden.

Samenvatting

  • Refresh Token — langlevende token voor het vernieuwen van access token zonder opnieuw inloggen
  • Korte TTL van access token (15–60 min) minimaliseert schade bij lekkage
  • Token rotation — elke vernieuwing retourneert een nieuwe refresh token, de oude wordt ongeldig gemaakt
  • Reuse detection — detecteert tokendiefstal en blokkeert de sessie
  • Opslag — iOS Keychain, Android EncryptedSharedPreferences (AES256-GCM)
  • Serverintrekking — verwijdering van refresh token uit de database bij logout of wachtwoordwijziging
  • Refresh token wordt nooit met gewone API-verzoeken meegestuurd

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook