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 خطر تساهل نشست را در مقایسه با ذخیره یک access token طولانی‌مدت 85% کاهش می‌دهد.

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 جدید",
  "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 در مقابل 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 خطر نشت توکن‌ها را در مقایسه با SharedPreferences عادی در صورت دسترسی فیزیکی به دستگاه تا 99.7% کاهش می‌دهد. برای افزایش امنیت، توصیه می‌شود انبارها را جدا کنید: 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 به این صورت کار می‌کند: سرور در پایگاه داده برای هر refresh token صادرشده یک علامت «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، مشترک باید یک خروج کامل انجام دهد: همه توکن‌های ذخیره‌شده (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 نباید برای endpoint‌های عادی برنامه قابل دسترسی باشد.

چقدر باید access token را به‌روز کنیم؟

در هر انقضای مدت — معمولاً هر 15–60 دقیقه. مشترک باید زمان انقضا را رهگیری کند (بررسی exp در JWT یت تایمر) و درخواست refresh را قبل از دریافت فعلی 401 آغاز کند. این از از دست رفتن داده‌ها در درخواست‌هایی که در لحظه انقضای توکن ارسال شده‌اند جلوگیری می‌کند.

آیا می‌توان refresh token را در سرور لغو کرد؟

بله، refresh token می‌توان و باید لغو شود. سرور فهرستی از refresh token‌های فعال (یا هاش‌های آن‌ها) را در پایگاه داده ذخیره می‌کند. در خروج، تغییر رمز عبور یا فعالیت مشکوک، سرور ثبت را از پایگاه داده حذف می‌کند و درخواست بعدی به‌روزرسانی با این توکن خطای invalid_grant را برمی‌گرداند.

در استفاده همزمان refresh token قدیمی توسط دو مشترک چه اتفاقی می‌افتد؟

در صورت پیاده‌سازی rotation با reuse detection: درخواست اول با موفقیت توکن‌ها را به‌روز می‌کند، دومی خطای invalid_grant دریافت می‌کند. سرور هم استفاده مجدد را ثبت می‌کند — نشست مسدود می‌شود، هر دو مشترک دسترسی را از دست می‌دهند. کاربر باید مجدداً وارد شود. این ایثار آسایش به خاطر امنیت است.

در iOS refresh token را کجا امن ذخیره کنیم؟

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 از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید