Mobil Uygulamalar için Refresh Token — özü, yenileme mekanizması ve güvenli saklama

Yazar: IT Sectr Yayınlanma: 2026-04-05 Okuma süresi: 9 dk

Refresh Token, kullanıcının kimlik bilgilerini yeniden girmesine gerek kalmadan yeni bir access token elde etmek için tasarlanmış özel bir uzun ömürlü token türüdür. OAuth 2.0 ve OpenID Connect mimarisinde, access tokenın kısa bir ömrü vardır (15–60 dakika), refresh tokenın ise önemli ölçüde daha uzun bir ömrü vardır (birkaç saatten aylara kadar). IETF RFC 6749, 2012’ye göre refresh_token, kesintisiz kimlik doğrulama sağlar: kullanıcı bir kez giriş yapar ve uygulama, iş akışını kesintiye uğratmadan erişimi otomatik olarak yeniler.

Önemli Noktalar

  • Refresh Token — yeniden giriş yapmadan yeni access token almak için uzun ömürlü token
  • Kısa ömürlü access token — sızıntı durumunda riski azaltır: saldırgan 15–30 dakika erişim elde eder
  • Token rotation — her yenileme isteği yeni bir refresh token döndürür, eskisi geçersiz kılınır
  • Güvenli depolama — iOS Keychain, Android EncryptedSharedPreferences, asla NSUserDefaults’ta değil
  • Refresh token yeniden kullanım tespiti — hırsızlığa karşı koruma: çalınmış bir refresh token kullanılırsa oturum engellenir

Refresh Token Nedir?

Refresh Token, istemci uygulamasının mevcut access tokenın süresi dolduktan sonra yeni bir access token almak için kullandığı bir kimlik bilgisidir. Access tokenın aksine, refresh_token her API isteğiyle gönderilmez — istemcide güvenli bir depoda saklanır ve yalnızca kimlik doğrulama sunucusunun token endpoint’i ile iletişim kurarken kullanılır.

Temel fikir, farklı ömürlere sahip iki tokenı ayırmaktır. Kısa TTL’ye sahip bir access token, ele geçirilmesi durumunda saldırı penceresini azaltır: bir access token çalınırsa, saldırgan onu yalnızca birkaç dakika kullanabilir. Refresh Token, normal isteklerle asla iletilmemesi gerçeğiyle korunur — yalnızca token endpoint’e güvenli bir kanal aracılığıyla iletilir. Bu, çalınmasını önemli ölçüde zorlaştırır.

OAuth Security Workshop, 2025’e göre, refresh token rotation uygulamak, tek bir uzun ömürlü access token saklamaya kıyasla oturum ele geçirme riskini %85 oranında azaltır.

Refresh Token Nasıl Çalışır

Yenileme süreci, istemcinin HTTP 401 Unauthorized yanıtı alması veya access tokenın süresinin dolduğunu tespit etmesiyle (JWT’de exp kontrolü) başlatılır. İstemci, grant_type=refresh_token ve istek gövdesinde refresh_token ile sunucunun token endpoint’ine POST isteği gönderir. Sunucu, refresh_tokenın geçerliliğini, süresini ve client_id ile ilişkisini doğrular. Her şey doğruysa — sunucu yeni bir access token ve isteğe bağlı olarak yeni bir refresh_token döndürür.

Token Yenileme Akışı

Yenileme isteği şeması şöyledir: istemci, /oauth/token adresine grant_type=refresh_token, refresh_token={token} ve client_id={id} parametreleriyle POST gönderir. Sunucu, yeni bir access token ve süre sonu ile JSON döndürür:

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

Refresh token rotation (yeni bir refresh_token döndürmek) OAuth 2.0 Security Best Current Practice (RFC 9700) tarafından önerilir. Eski refresh_token aynı anda geçersiz kılınır. Bir saldırgan eski refresh_tokenı çaldıysa ve yasal istemciden önce kullanmayı başardıysa, sunucu yeniden kullanımı tespit eder — reuse detection — ve tüm oturumu engeller.

Refresh Token ve Access Token

Access token ve refresh_token farklı işlevler görür ve temelde farklı güvenlik özelliklerine sahiptir. Access token, API için geçici bir geçiş kartıyken, refresh_token yeni geçiş kartları almak için uzun vadeli bir izindir.

ParametreAccess TokenRefresh Token
Ömür15–60 dakikaGün, hafta veya ay
İletim sıklığıHer API isteğiSadece yenileme sırasında
İstemci depolamaBellek / kısa vadeliGüvenli (Keychain / EncryptedSharedPrefs)
KapsamBelirli izin setiTam kullanıcı izinleri
İptalKısa TTL ileSunucu kara listesi / silme
BiçimJWT veya opaqueGenellikle opaque (rastgele dize)

Access token neden uzun ömürlü olamaz

Access token için kısa TTL bilinçli bir güvenlik takasıdır. Bir access token çalınırsa (trafik ele geçirme, günlük sızıntısı veya cihazdaki kötü amaçlı yazılım yoluyla), bir saldırganın onu kullanabileceği süre 15–60 dakika ile sınırlıdır. Refresh_token, her istekle asla iletilmediği için korunur — onu ele geçirmek, token endpoint’e yönelik hedefli bir saldırı gerektirir. Auth0 Security Team, 2025’e göre, tehlikeye atılmış access token’ların %90’ı güvenli olmayan ağ bağlantıları yoluyla ele geçirilmiştir — refresh_tokenın kendi mimarisi tarafından korunduğu şey tam olarak budur.

Refresh Token Güvenliği

Refresh_token güvenliği tüm kimlik doğrulama şemasının kritik bir unsurudur. Refresh_token, uzun bir süre boyunca hesaba tam erişim sağladığı için koruması maksimum düzeyde olmalıdır. OWASP ve OAuth Security Best Practices belirli gereksinimler yayınlar.

Mobil cihazlarda refresh token depolama

Doğru depolama platforma bağlıdır. iOS’ta — kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly erişimli Keychain. Bu, cihaz şifresi kaldırıldığında tokenın erişilemez olmasını sağlar. Android’de — Android Keystore’da ana anahtarla AndroidX Security kitaplığından EncryptedSharedPreferences. Token dosya sistemi düzeyinde şifrelenir ve root erişimiyle bile erişilemez. Yasak: refresh_tokenı SharedPreferences, NSUserDefaults, düz metin dosyaları veya şifrelemesiz Base64’te saklamak.

Google Security Blog, 2025’e göre, AES256-GCM ile EncryptedSharedPreferences, cihaza fiziksel erişim durumunda normal SharedPreferences’a kıyasla token sızıntısı riskini %99,7 oranında azaltır. Güvenliği artırmak için depolamanın ayrılması da önerilir: access_token bellekte (kısa vadeli erişim) saklanabilirken, refresh_token yalnızca korumalı sistem deposunda (Keychain / Keystore) saklanmalıdır. Uygulama sistemden bir ön plan sinyali alırsa, kullanıcı etkileşime başlamadan önce refresh_token kontrol edilir ve gerekiyorsa yenilenir.

Refresh Token Rotation

Refresh token rotation, bir access tokenı yenileme isteğinin her seferinde yeni bir refresh_token döndürdüğü ve eskisinin iptal edildiği bir mekanizmadır. Bir saldırgan refresh_tokenı çaldıysa ve kullanırsa, yasal istemci bir sonraki yenileme girişiminde bir hata alır — sunucu, refresh_tokenın zaten kullanıldığını tespit eder (reuse detection). Rotation, mobil ortamda uzun ömürlü tokenlarla çalışan tüm sistemler için OAuth 2.0 Security Best Current Practice (RFC 9700)’nin zorunlu bir tavsiyesidir.

Yeniden Kullanım Tespiti

Tespit algoritması şu şekilde çalışır: sunucu, veritabanında yayınlanan her refresh_token için bir “kullanıldı” işareti depolar. Bir yenileme isteğinde sunucu kontrol eder — refresh_token zaten kullanılmış olarak işaretlenmişse, bir yeniden kullanım girişimi olmuştur. Sunucu, o oturumun tüm refresh_tokenlarını derhal geçersiz kılar ve erişimi engeller. Yasal kullanıcı giriş sayfasına yönlendirilir.

OAuth Security Workshop, 2025’e göre, rotation + reuse detection uygulamak, çalınmış bir refresh_token aracılığıyla başarılı bir saldırı olasılığını %23’ten %0,3’e düşürür. Yeniden kullanım tespitini uygulamak için sunucu, client_id ile eşleştirilmiş son yayınlanan refresh_tokenın karmasını depolar. Bir yenileme isteğinde sunucu, sunulan refresh_tokenı saklananla karşılaştırır — eşleşmezlerse, yeniden kullanım olmuştur ve tüm token zinciri iptal edilir.

invalid_grant hatası alındığında, istemci tam bir çıkış yapmalıdır: depolanan tüm tokenları (access ve refresh) temizleyin, cihazdaki mevcut oturumu sonlandırın ve kullanıcıyı giriş ekranına yönlendirin. Yeniden kimlik doğrulama, öncekiyle ilişkisiz yeni bir token zinciri oluşturur. Bu hatayı görmezden gelmek ve yenilemeyi yeniden denemek, yeniden kullanım tespiti nedeniyle engellemeye yol açacaktır.

Kotlin’de Uygulama

Android için Kotlin’de istemci tarafı token yenileme uygulaması örneği. Uygulama, HTTP 401 yanıtını yakalar, bir yenileme isteği başlatır ve yeni access_token ile orijinal isteği yeniden dener. OkHttp Interceptor kullanılır — her istekte mantığı kopyalamadan otomatik token yönetimi için önemli bir bileşen.

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 süresi doldu — refresh token ile yenileniyor
        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")
        // Rotation sırasında yeni refresh token kaydet
        saveTokens(newAccessToken, json.optString("refresh_token"))
        return newAccessToken
    }
}

Sıkça Sorulan Sorular

Refresh token, access token’dan nasıl farklıdır?

Access token — API erişimi için kısa ömürlü token, her istekle gönderilir. Refresh_token — yeni access_token almak için uzun ömürlü token, yalnızca token endpoint’e gönderilir. Refresh_token, uygulamanın normal API uç noktalarından erişilebilir olmamalıdır.

Access token ne sıklıkta yenilenmelidir?

Her süre sonunda — genellikle her 15–60 dakikada bir. İstemci, süresinin dolma süresini izlemeli (JWT’de exp kontrolü veya zamanlayıcı kullanarak) ve fiilen 401 almadan önce yenileme isteğini başlatmalıdır. Bu, tokenın süresinin dolduğu anda gönderilen isteklerde veri kaybını önler.

Sunucuda refresh token iptal edilebilir mi?

Evet, refresh_token iptal edilebilir ve edilmelidir. Sunucu, veritabanında aktif refresh_tokenların (veya karmalarının) bir listesini tutar. Çıkış, şifre değişikliği veya şüpheli etkinlik durumunda sunucu, veritabanından girişi kaldırır ve bu token ile bir sonraki yenileme isteği invalid_grant hatası döndürür.

İki istemci aynı anda eski refresh tokenı kullanırsa ne olur?

Rotation ve yeniden kullanım tespiti etkinken: ilk istek tokenları başarıyla yeniler, ikincisi invalid_grant hatası alır. Sunucu ayrıca yeniden kullanımı kaydeder — oturum engellenir, her iki istemci de erişimi kaybeder. Kullanıcının yeniden giriş yapması gerekir. Bu, güvenlik için rahatlıktan ödün verir.

iOS’ta refresh token nerede güvenle saklanır?

Refresh_token, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly özelliğiyle Keychain’de saklanmalıdır. Bu, token şifrelemesini, şifre kaldırıldığında erişilemezliği garanti eder ve iCloud senkronizasyonunu önler. Tokenı saklamak için UserDefaults veya CoreData kullanmak kesinlikle yasaktır.

Özet

  • Refresh Token — yeniden giriş yapmadan access_tokenı yenilemek için uzun ömürlü token
  • Access_tokenın kısa TTL’si (15–60 dk) sızıntıdan kaynaklanan hasarı en aza indirir
  • Token rotation — her yenileme yeni bir refresh_token döndürür, eskisi geçersiz kılınır
  • Yeniden kullanım tespiti — token hırsızlığını tespit eder ve oturumu engeller
  • Depolama — iOS Keychain, Android EncryptedSharedPreferences (AES256-GCM)
  • Sunucu iptali — çıkış veya şifre değişikliğinde veritabanından refresh_tokenı kaldırma
  • Refresh token normal API istekleriyle asla iletilmez

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun