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، refresh token با هر درخواست API ارسال نمیشود — در یک ذخیرهساز امن در طرف مشترک ذخیره میشود و تنها در زمان مراجعه به token endpoint سرور احراز هویت استفاده میشود.
ایده اصلی جداسازی دو توکن با عمر مختلف است. Access token با TTL کوتاه پنجره حمله را در زمان رهگیری کاهش میدهد: اگر access token دزدیده شود، مهاجم میتواند آن را تنها چند دقیقه استفاده کند. Refresh token با این ویژگی که هرگز با درخواستهای عادی ارسال نمیشود محافظت میشود — تنها از طریق یک کانال امن به token endpoint. این دزدیدن آن را بسیار دشوارتر میکند.
به گزارش OAuth Security Workshop, 2025، پیادهسازی refresh token با rotation خطر تساهل نشست را در مقایسه با ذخیره یک access token طولانیمدت 85% کاهش میدهد.
فرآیند بهروزرسانی زمانی آغاز میشود که مشترک پاسخ 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 جدید و تاریخ انقضا برمیگرداند:
{
"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 — و کل نشست را مسدود میکند.
Access token و refresh token کارکردهای مختلفی دارند و ویژگیهای امنیتی اساساً متفاوتی دارند. Access token یک گذر موقت به API است، refresh token یک مجوز بلندمدت برای دریافت گذرهای جدید است.
| پارامتر | Access Token | Refresh Token |
|---|---|---|
| عمر | 15–60 دقیقه | روزها، هفتهها یا ماهها |
| دفعه ارسال | هر درخواست API | تنها در بهروزرسانی |
| ذخیرهساز مشترک | حافظه / کوتاهمدت | امن (Keychain / EncryptedSharedPrefs) |
| Scope | مجموعه مشخصی از دسترسیها | کل حوزه دسترسی کاربر |
| ابطال | از طریق TTL کوتاه | Blacklist سرور / حذف |
| فرمت | JWT یا opaque | معمولاً opaque (رشته تصادفی) |
TTL کوتاه access token — یک معامله آگاهانه امنیتی است. اگر access token دزدیده شود (از طریق رهگیری ترافیک، نشت سجل، نرمافزار مضر روی دستگاه)، زمانی که مهاجم میتواند آن را استفاده کند به 15–60 دقیقه محدود است. Refresh token با این ویژگی که هرگز با هر درخواست ارسال نمیشود محافظت میشود — رهگیری آن نیازمند یک حمله مستقیم به token endpoint است. به گزارش Auth0 Security Team, 2025، 90% از access tokenهای تساهلیافته از طریق اتصالات شبکه ناامن رهگیری شدهاند — دقیقاً چیزی که refresh token توسط معماری خود از آن محافظت میکند.
امنیت refresh token — عنصر بسیار مهم کل شما احراز هویت است. از آنجایی که refresh token دسترسی کامل به حساب را برای مدت طولانی فراهم میکند، حفاظت از آن باید حداکثر باشد. OWASP و OAuth Security Best Practices نیازمندیهای مشخصی را منتشر میکنند.
ذخیره صحیح به پلتفرم بستگی دارد. در 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 — مکانیزمی است که در آن هر درخواست بهروزرسانی access token یک refresh token جدید برمیگرداند و قدیمی لغو میشود. اگر مهاجمی refresh token را دزدیده و از آن استفاده کند، مشترک قانونی در مرحله بعدی تلاش برای بهروزرسانی خطا دریافت میکند — سرور تشخیص میدهد که refresh token قبلاً استفاده شده است (reuse detection). Rotation یک توصیه اجباری OAuth 2.0 Security Best Current Practice (RFC 9700) برای همه سیستمهایی است که با توکنهای طولانیمدت در محیط موبایل کار میکنند.
الگوریتم 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 برای Android. برنامه پاسخ HTTP 401 را رهگیری میکند، درخواست refresh را فراخوان میکند و درخواست اصلی را با access token جدید تکرار میکند. OkHttp Interceptor استفاده میشود — یک مؤلفه کلیدی برای مدیریت خودکار توکنها بدون تکرار منطق در هر درخواست.
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
}
}
سوالات متداول
Access token — توکن کوتاهمدت برای دسترسی به API، با هر درخواست ارسال میشود. Refresh token — توکن طولانیمدت برای دریافت access token جدید، تنها به token endpoint ارسال میشود. Refresh token نباید برای endpointهای عادی برنامه قابل دسترسی باشد.
در هر انقضای مدت — معمولاً هر 15–60 دقیقه. مشترک باید زمان انقضا را رهگیری کند (بررسی exp در JWT یت تایمر) و درخواست refresh را قبل از دریافت فعلی 401 آغاز کند. این از از دست رفتن دادهها در درخواستهایی که در لحظه انقضای توکن ارسال شدهاند جلوگیری میکند.
بله، refresh token میتوان و باید لغو شود. سرور فهرستی از refresh tokenهای فعال (یا هاشهای آنها) را در پایگاه داده ذخیره میکند. در خروج، تغییر رمز عبور یا فعالیت مشکوک، سرور ثبت را از پایگاه داده حذف میکند و درخواست بعدی بهروزرسانی با این توکن خطای invalid_grant را برمیگرداند.
در صورت پیادهسازی rotation با reuse detection: درخواست اول با موفقیت توکنها را بهروز میکند، دومی خطای invalid_grant دریافت میکند. سرور هم استفاده مجدد را ثبت میکند — نشست مسدود میشود، هر دو مشترک دسترسی را از دست میدهند. کاربر باید مجدداً وارد شود. این ایثار آسایش به خاطر امنیت است.
Refresh token را در Keychain با ویژگی kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly ذخیره کنید. این شیفره شدن توکن، غیرقابل دسترسی بودن در صورت برداشتن رمز و حذف همگامسازی از طریق iCloud را تضمین میکند. استفاده از UserDefaults یا CoreData برای ذخیره توکن به طور قطع ممنوع است.
نتیجه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید