تدفقات OAuth من الواجهة الأمامية
نفّذ تدفق Authorization Code مع PKCE في SPA، واستبدل الرمز المميز برموز الوصول، وخزّن رموز الوصول بأمان، وتجنب التدفق الضمني
تدفقات OAuth من الواجهة الأمامية درس مجاني في Frontend Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Frontend Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Frontend Academy 4 دروس في المجموع.
ما هو OAuth؟
OAuth 2.0 هو بروتوكول تفويض: يحصل تطبيقك على إذن للتصرف نيابةً عن المستخدم لدى خدمة تابعة لجهة خارجية، مثل Google أو GitHub، من دون أن يرى كلمة مرور المستخدم إطلاقًا. ويُستخدم في ميزة تسجيل الدخول باستخدام Google وتطبيقات GitHub OAuth ومعظم أنظمة المصادقة الحديثة.
الأدوار الأساسية
مالك المورد: المستخدم. العميل: تطبيقك. خادم التفويض: موفّر OAuth، مثل Google أو Auth0. خادم المورد: واجهة API المحمية بواسطة access token.
تدفق Authorization Code
التدفق القياسي الآمن لتطبيقات الخادم: 1) أعد توجيه المستخدم إلى صفحة تسجيل الدخول لدى الموفّر. 2) يسجّل المستخدم الدخول ويمنح الموافقة. 3) يعيد الموفّر توجيه المستخدم مع code. 4) يستبدل الخادم code بـ access token (وهو سر لا يُستخدم إلا على الخادم).
لماذا نستخدم PKCE مع تطبيقات SPA؟
لا يمكن لتطبيقات SPA الاحتفاظ بسر العميل، لأنه سيكون موجودًا في حزمة المتصفح. يستبدل PKCE (Proof Key for Code Exchange) السر بمتحقق وتحدٍّ للرمز يُنشآن لكل طلب. وأصبح هذا الآن المعيار لجميع عملاء OAuth العامين.
تدفق PKCE خطوة بخطوة
1) أنشئ code_verifier عشوائيًا. 2) احسب SHA-256 له لتحصل على code_challenge. 3) أعد التوجيه إلى /authorize مع التحدي. 4) بعد الموافقة، استلم code. 5) استبدل code مع verifier بـ access token. يتحقق الموفّر من أن challenge يساوي hash(verifier).
إنشاء Code Verifier وChallenge
إن verifier عبارة عن سلسلة عشوائية، أما challenge فهو قيمة SHA-256 الخاصة بها بعد ترميزها بتنسيق base64-URL.
function base64url(arr) {
return btoa(String.fromCharCode(...arr))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
async function generatePKCE() {
const arr = new Uint8Array(32);
crypto.getRandomValues(arr);
const verifier = base64url(arr);
const hash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));
const challenge = base64url(new Uint8Array(hash));
return { verifier, challenge };
}إعادة التوجيه إلى الموفّر
أنشئ عنوان URL الخاص بالتفويض مع challenge وstate (للحماية من CSRF) وscopes.
const { verifier, challenge } = await generatePKCE();
const state = crypto.randomUUID();
sessionStorage.setItem('pkce_verifier', verifier);
sessionStorage.setItem('oauth_state', state);
const url = new URL('https://accounts.google.com/o/oauth2/v2/auth');
url.searchParams.set('client_id', CLIENT_ID);
url.searchParams.set('redirect_uri', `${origin}/auth/callback`);
url.searchParams.set('response_type', 'code');
url.searchParams.set('scope', 'openid email profile');
url.searchParams.set('code_challenge', challenge);
url.searchParams.set('code_challenge_method', 'S256');
url.searchParams.set('state', state);
window.location.href = url.toString();معالجة Callback
يعيد الموفّر التوجيه إلى عنوان callback الخاص بك مع ?code=...&state=.... تحقّق من state لمنع CSRF، ثم استبدل code.
// /auth/callback page:
const params = new URLSearchParams(window.location.search);
const code = params.get('code');
const returnedState = params.get('state');
const expected = sessionStorage.getItem('oauth_state');
if (returnedState !== expected) throw new Error('Bad state');
const verifier = sessionStorage.getItem('pkce_verifier');
const tokens = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code,
client_id: CLIENT_ID,
redirect_uri: `${origin}/auth/callback`,
code_verifier: verifier
})
}).then(r => r.json());
// tokens: { access_token, id_token, refresh_token, expires_in }تخزين الرموز بأمان
أفضل ممارسة: لا تخزّن access tokens في localStorage، إذ يمكن سرقتها عبر XSS. الخيارات: 1) تخزينها في الذاكرة فقط (تُمسح عند التحديث، ويلزم إعادة المصادقة). 2) تخزينها في ملف تعريف ارتباط HttpOnly (يضبطه الخادم الخلفي بعد تدفق PKCE، ولا يستطيع JavaScript سرقته).
تجنب Implicit Flow
يعيد التدفق الضمني القديم access token مباشرةً في جزء URL. وقد أوقفته OAuth 2.0 Security BCP لأنه يسرّب الرموز إلى سجل المتصفح وعناوين الإحالة. استخدم Authorization Code مع PKCE دائمًا.
Refresh Tokens
تنتهي صلاحية access tokens، عادةً بعد ساعة واحدة. ويحصل refresh token، وهو أطول عمرًا، على access tokens جديدة دون تدخل المستخدم. بالنسبة إلى تطبيقات SPA، تُرسل refresh tokens بشكل متزايد عبر ملفات تعريف ارتباط HttpOnly، وليس عبر localStorage مطلقًا.
ID Tokens مقابل Access Tokens
ID token (OpenID Connect): JWT يثبت هوية المستخدم. Access token: قيمة مبهمة أو JWT تُستخدم لاستدعاء واجهات API. تحقّق من توقيع ID token وclaims الخاصة به (iss وaud وexp وnonce) قبل الوثوق به.
مكتبات المصادقة
لا تطوّر نظامك الخاص. استخدم: oidc-client-ts لـ OIDC الخام، وauth0/spa-js لـ Auth0، و@clerk/clerk-react لـ Clerk، وNextAuth.js/Auth.js لـ Next، وNuxt-auth لـ Nuxt. تتولى هذه المكتبات PKCE والتحديث والتخزين.
فحص سريع
لماذا يجب أن تستخدم تطبيقات الصفحة الواحدة PKCE (Proof Key for Code Exchange) مع تدفق Authorization Code بدلًا من استخدام تدفق Authorization Code الأساسي وحده؟
مراجعة: OAuth في الواجهة الأمامية
يُعد Authorization Code مع PKCE المعيار الحديث لتطبيقات SPA. أنشئ verifier وS256 challenge لكل طلب. أعد التوجيه إلى /authorize مع challenge وstate. تحقّق من state عند callback. استبدل code مع verifier بالرموز. لا تستخدم Implicit flow مطلقًا. فضّل ملفات تعريف الارتباط HttpOnly لتخزين الرموز. استخدم المكتبات (auth0-spa-js وoidc-client-ts وNextAuth)، ولا تطوّر نظامك الخاص.
تعلم HTML مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 41
- الدروس
- 163
الأسئلة الشائعة
هل درس «تدفقات OAuth من الواجهة الأمامية» مجاني؟
نعم — نص درس «تدفقات OAuth من الواجهة الأمامية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Frontend Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Frontend Academy 4 دروس في المجموع.
ماذا ستتعلم في «تدفقات OAuth من الواجهة الأمامية»؟
نفّذ تدفق Authorization Code مع PKCE في SPA، واستبدل الرمز المميز برموز الوصول، وخزّن رموز الوصول بأمان، وتجنب التدفق الضمني تتمرن على Frontend Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Frontend Academy؟
لا تُشترط خبرة سابقة. Frontend Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «تدفقات OAuth من الواجهة الأمامية»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Frontend Academy هذا؟
نعم. كل درس في Frontend Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- منع XSS: ترميز المخرجات وCSP
- CSRF: ملفات تعريف الارتباط والرموز SameSite
- Content Security Policy: nonce وhash
- تدفقات OAuth من الواجهة الأمامية