OAuth 2.0 هو بروتوكول تفويض قياسي صناعي يمنح التطبيقات الخارجية وصولاً محدوداً إلى موارد المستخدم دون مشاركة بيانات اعتماده. أصبح البروتوكول المعيار الفعلي للتفويض المفوض في تطبيقات الويب والجوال، وتستخدمه منصات مثل Google و Facebook و Apple و GitHub. وفقاً لـ IETF RFC 6749 (2025)، يُستخدم OAuth 2.0 في أكثر من 85% من جميع تكاملات API التي تتطلب وصولاً مفوضاً إلى البيانات.
الملخص
OAuth 2.0 هو بروتوكول تفويض مُعرّف في IETF RFC 6749 يسمح للتطبيقات الخارجية بالحصول على وصول محدود إلى موارد المستخدم دون الكشف عن اسم المستخدم وكلمة المرور. يحل البروتوكول مشكلة أساسية في نموذج كلمة المرور: التطبيق الذي تثق به بكلمة مرورك يحصل على وصول غير مقيد إلى جميع بيانات الحساب. يستبدل OAuth 2.0 هذا النهج بإصدار رمز مؤقت مع نطاق وصول محدد بشكل صريح.
بنية OAuth 2.0 هي التفويض المفوض. المستخدم (Resource Owner) يفوض تطبيقاً (Client) للوصول إلى بياناته المخزنة على خادم الموارد (Resource Server) عبر وسيط: خادم التفويض (Authorization Server). يصدر خادم التفويض Access Token: سلسلة تشفيرية يقدمها التطبيق لخادم الموارد للوصول إلى البيانات. فرق مهم بين OAuth 2.0 و SAML و OpenID Connect: OAuth 2.0 يحل مهمة التفويض (ما هو مسموح به)، وليس المصادقة (من هو المستخدم). للمصادقة فوق OAuth 2.0 يُبنى بروتوكول OpenID Connect (OIDC).
البروتوكول مدعوم من جميع المنصات الرئيسية. تستخدم Google OAuth 2.0 للوصول إلى Google APIs (Gmail و Drive و Calendar)، و Facebook لـ Graph API، و Apple لـ Sign in with Apple (ASAuthorizationAppleIDProvider)، و GitHub للوصول إلى المستودعات. في سياق تطوير الجوال، OAuth 2.0 هو الآلية القياسية لتكامل الخدمات الخارجية: تسجيل الدخول عبر الشبكات الاجتماعية، الوصول إلى التخزين السحابي، ونشر المحتوى نيابة عن المستخدم.
يحدد بروتوكول OAuth 2.0 أربعة أدوار يشكل تفاعلها دورة التفويض الكاملة. فهم كل دور ضروري للتنفيذ الصحيح للبروتوكول في تطبيق محمول.
| الدور | الوصف | مثال |
|---|---|---|
| Resource Owner | مالك البيانات: المستخدم الذي يسمح بالوصول إلى موارده | مستخدم التطبيق الذي ينقر على «تسجيل الدخول عبر Google» |
| Client | التطبيق الذي يطلب الوصول إلى الموارد نيابة عن المالك | تطبيق محمول يحتاج إلى الوصول إلى Google Drive |
| Authorization Server | الخادم الذي يصدر الرموز بعد المصادقة والتفويض | accounts.google.com: خادم تفويض Google |
| Resource Server | API التي توفر الوصول إلى الموارد المحمية باستخدام الرمز | www.googleapis.com: خادم موارد Google Drive API |
الكيانات الرئيسية للبروتوكول هي Access Token و Refresh Token و Authorization Code. Access Token هو رمز قصير العمر (عادة 15–60 دقيقة) يُقدم لخادم الموارد مع كل طلب بيانات. Refresh Token هو رمز طويل العمر (أيام أو أسابيع) يُستخدم للحصول على Access Token جديد دون حاجة المستخدم لتسجيل الدخول مرة أخرى. Authorization Code هو رمز مؤقت يُصدر بعد تفويض المستخدم ويتم استبداله بـ Access Token و Refresh Token.
يحدد OAuth 2.0 عدة Grant Types: سيناريوهات الحصول على الرمز، كل منها مصمم لنوع معين من العميل وسياق أمني. اختيار Grant Type الصحيح هو قرار معماري حاسم عند تصميم التفويض في تطبيق محمول.
Grant Types الرئيسية: Authorization Code (الأكثر أماناً للتطبيقات المحمولة والويب مع مكون خادم)، Authorization Code مع PKCE (Proof Key for Code Exchange: للتطبيقات المحمولة و SPA بدون خلفية خادم)، Client Credentials (لمصادقة خادم إلى خادم دون مشاركة المستخدم)، Resource Owner Password Credentials (مهمل: ينقل كلمة المرور مباشرة). PKCE هو امتداد إلزامي للعملاء العموميين (تطبيقات الجوال، SPA) وفقاً لتوصيات OAuth Security BCP (RFC 9700).
Authorization Code Flow مع PKCE هو التكوين الموصى به لـ OAuth 2.0 لتطبيقات الجوال الأصلية. يضيف PKCE (Proof Key for Code Exchange) طبقة حماية إضافية تمنع هجمات اعتراض authorization code. البروتوكول موصوف في IETF RFC 7636.
تسلسل الخطوات: (1) يولد العميل code_verifier عشوائياً (سلسلة من 43–128 حرفاً باستخدام أحرف غير محجوزة فقط)، (2) يحسب العميل code_challenge = SHA-256(code_verifier)، (3) يفتح العميل متصفحاً لتفويض المستخدم على Authorization Server، ويمرر code_challenge، (4) بعد التفويض الناجح، يعيد الخادم authorization code إلى التطبيق عبر مخطط URI مخصص (deep link)، (5) يرسل العميل authorization code + code_verifier إلى الخادم، (6) يتحقق الخادم من SHA-256(code_verifier) === code_challenge ويصدر Access Token + Refresh Token.
ميزة PKCE: حتى إذا اعترض المهاجم authorization code في مخطط URI، فلن يتمكن من استبداله برمز بدون code_verifier المعروف فقط للعميل الشرعي. في تطبيقات الجوال، لفتح المتصفح يجب استخدام Chrome Custom Tabs (Android) أو ASWebAuthenticationSession (iOS): هذا يضمن أن متصفح النظام لا يمكنه الوصول إلى code_verifier من ذاكرة التطبيق.
AppAuth هو التنفيذ المرجعي لـ OAuth 2.0 و OpenID Connect للتطبيقات الأصلية، الموصى به من IETF. تدعم المكتبة PKCE و Chrome Custom Tabs ومخططات URI المخصصة لإعادة authorization code والتحديث التلقائي للرموز. AppAuth لنظام Android متاح عبر التبعية `net.openid:appauth:0.11.1`.
val serviceConfig = AuthorizationServiceConfiguration.fromUrl(
Uri.parse("https://accounts.google.com/.well-known/openid-configuration")
)
val request = AuthorizationRequest.Builder(
serviceConfig,
"CLIENT_ID.apps.googleusercontent.com",
ResponseTypeValues.CODE,
Uri.parse("com.example.app:/oauth2callback")
)
.setScope("openid profile email")
.setCodeVerifier(
CodeVerifierUtil.generateRandomCodeVerifier()
)
.build()
val authService = AuthorizationService(context)
val intent = authService.getAuthorizationRequestIntent(request)
// تشغيل Chrome Custom Tab للتفويض
startActivityForResult(intent, REQUEST_CODE_AUTH)
بعد استلام authorization code (onActivityResult)، يستبدله التطبيق بـ Access Token و Refresh Token عبر TokenRequest. تُحفظ الرموز في SharedPreferences مع التشفير عبر EncryptedSharedPreferences (Android Security Crypto). يجب تخزين Refresh Token في KeyStore: مخزن مفاتيح أجهزة لا يمكن للتطبيقات الأخرى الوصول إليه. عند انتهاء صلاحية Access Token، يستخدم التطبيق Refresh Token للحصول على جديد: لا يحتاج المستخدم لإعادة المصادقة.
// استبدال authorization code بالرموز
val data = intent?.data ?: return
val resp = AuthorizationResponse.fromIntent(data)
val exchangeReq = resp?.createTokenExchangeRequest()
?: return
authService.performTokenRequest(
exchangeReq,
ClientAuthentication.none()
) { tokenResp, ex ->
if (tokenResp != null) {
// تم استلام Access Token و Refresh Token
val accessToken = tokenResp.accessToken
val refreshToken = tokenResp.refreshToken
// حفظ في EncryptedSharedPreferences
saveTokens(accessToken, refreshToken)
}
}
يوضح الكود أعلاه دورة OAuth 2.0 الكاملة مع PKCE: إنشاء تكوين الخادم عبر OpenID Connect Discovery، توليد طلب تفويض مع code_verifier، تشغيل Chrome Custom Tab، استقبال authorization code عبر مخطط URI مخصص، واستبدال الرمز برموز عبر Token Request. من المهم معالجة انتهاء صلاحية Access Token: عند استلام استجابة HTTP 401 من Resource Server، يجب على التطبيق استخدام Refresh Token للحصول على Access Token جديد وإعادة تنفيذ الطلب.
OAuth 2.0 هو بروتوكول معقد مع العديد من نواقل الهجوم. يصف IETF Security BCP (RFC 9700) أكثر من 20 فئة من ثغرات OAuth 2.0. بالنسبة للتطبيقات المحمولة، الأكثر خطورة هي: اعتراض authorization code عبر مخططات URI المخصصة، هجمات CSRF على نقاط نهاية الاستدعاء، سرقة Refresh Token من تخزين غير آمن، وانتحال العميل عبر اعتراض النية.
تشمل الحماية من هذه الهجمات إجراءات إلزامية: (1) PKCE مع S256 code_challenge: يمنع اعتراض authorization code حتى عند اعتراض مخطط URI؛ (2) استخدام معامل nonce أو state لمنع CSRF: يتحقق الخادم من أن authorization code يتوافق مع الطلب الأصلي؛ (3) تخزين Refresh Token فقط في KeyStore (Android) أو Keychain (iOS): ليس في SharedPreferences أو UserDefaults؛ (4) استخدام TLS مع Certificate Pinning للحماية من MITM في طبقة النقل؛ (5) التحقق من redirect_uri: يجب على خادم التفويض التحقق بدقة من تطابقه مع URI المسجل.
توصيات إضافية من IETF: يجب على التطبيقات المحمولة استخدام AppAuth أو مكتبات مماثلة خضعت لتدقيقات أمنية؛ عدم الاعتماد على WebView لـ OAuth (لا يعزل WebView البيانات عن التطبيق الرئيسي)؛ تنفيذ التدوير التلقائي لـ Refresh Token (يمكن استخدام كل Refresh Token مرة واحدة فقط)؛ إضافة Certificate Pinning عبر TrustManager لنظام Android و URLSession لنظام iOS. يساعد OpenID Connect Discovery (نقطة نهاية well-known) في تحديد نقاط نهاية خادم التفويض الصحيحة تلقائياً وتجنب إعادة التوجيه إلى صفحات التصيد.
الأسئلة الشائعة
OAuth 2.0 هو بروتوكول تفويض (ما هو مسموح به؟)، بينما OpenID Connect (OIDC) هو بروتوكول مصادقة (من هو المستخدم؟). يُبنى OIDC فوق OAuth 2.0 ويضيف ID Token: رمز JWT يحتوي على معلومات حول هوية المستخدم. يوفر OAuth 2.0 Access Token، ويكمله OIDC بـ ID Token ونقطة نهاية UserInfo للحصول على ملف تعريف المستخدم.
Bearer Token هو Access Token يُقدم في رأس HTTP Authorization: Bearer. خطورته تكمن في أن أي شخص يمتلك الرمز يمكنه الوصول إلى المورد: الرمز غير مرتبط بالعميل. لذلك، يجب نقل Bearer Token فقط عبر TLS (HTTPS)، وأن يكون له عمر قصير (15–60 دقيقة)، وألا يُخزن أبداً في السجلات أو معلمات URL.
التطبيقات المحمولة هي عملاء عموميون ليس لديهم client_secret (لا يمكن حماية السر في APK/IPA). بدون PKCE، يمكن للمهاجم اعتراض authorization code عبر مخطط URI مخصص (مثلاً malformed://callback?code=ABC) واستبداله برمز. PKCE يضيف code_verifier معروفاً فقط للتطبيق، مما يجعل الرمز المعترض عديم الفائدة.
Access Token النموذجي يعيش 15–60 دقيقة (قابل للتكوين على خادم التفويض). مع كل طلب HTTP إلى Resource Server، يتم التحقق من الاستجابة: إذا كان الرمز 401، يشغل التطبيق Refresh Token Flow للحصول على Access Token جديد. يعيش Refresh Token من 24 ساعة إلى عدة أشهر، حسب سياسة أمان المزود. عند تغيير Refresh Token، يتم إبطال القديم.
لا: IETF Security BCP (RFC 9700) يحظر WebView لـ OAuth 2.0 في التطبيقات المحمولة. لا يعزل WebView ملفات تعريف الارتباط والبيانات عن التطبيق الرئيسي، مما يسمح للتطبيق باعتراض بيانات اعتماد المستخدم. بدلاً من WebView، استخدم Chrome Custom Tabs (Android) أو ASWebAuthenticationSession (iOS): مكونات متصفح النظام المعزولة عن التطبيق.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا