أربع خطوات للدمج
الواجهة الأمامية تبدأ الدخول
أنشئ نسخة عبر createTutuId({ baseUrl, clientId }) من @tutu/id-sdk واستدعِ idSdk.startLogin() عند النقر. تُولّد SDK زوج PKCE وتحوّل إلى صفحة تفويض TutuId.
المستخدم يُصرّح في TutuId
في شاشة الموافقة /oauth/authorize ينقر المستخدم «سماح» (تُتخطّى تلقائيًا إن سبق التفويض). بعد تحقّق TutuId من client_id وقائمة redirect_uri المسموح بها، يعيد التوجيه إلى /auth/callback لديك مع رمز تفويض.
صفحة الاستدعاء تجلب الـ code
في /auth/callback استدعِ idSdk.completeCallback() للحصول على { code, codeVerifier }. سلّم هاتين القيمتين إلى خادمك الخلفي، ولا تبادل الـ token مباشرة في المتصفح.
الخادم الخلفي يبادل الـ token ← ينشئ الحساب
يبادل خادمك code + codeVerifier بـ access_token، ويستدعي /userinfo للحصول على { sub, email, emailVerified, ... }، ثم يربط أو ينشئ حسابًا محليًا حسب sub، ويُصدر جلستك الخاصة.
★ الحماية من الاستيلاء على الحساب (إلزامي)
خادمك الخلفي لا يجوز له ربط أو إنشاء حساب محلي إلا حسب sub (المعرّف الفريد للحساب). وفقط عندما emailVerified === true يمكنك ربط حساب محلي قائم بالبريد؛ وإلا فأنشئ حسابًا مستقلًا واترك البريد فارغًا.
السبب: قد يسجّل مهاجم حساب Tutu مسبقًا ببريد الضحية؛ والدمج ببريد غير مُتحقَّق يسلّم حساب الضحية المحلي. هذا خط أحمر بمستوى CVE.
مرجع واجهة SDK
@tutu/id-sdk · من جانب العميل بالكامل، بلا اعتماديات (يتطلب Web Crypto + sessionStorage).
createTutuId({ baseUrl, clientId, redirectUri? }) ينشئ نسخة SDK. القيمة الافتراضية لـ redirectUri هي ${location.origin}/auth/callback وتتكيّف مع dev/prod.
startLogin(scope?) يُولّد زوج PKCE ويحوّل إلى صفحة التفويض، بادئًا «الدخول عبر Tutu».
trySilentLogin(scope?) الدخول الصامت: إن وُجدت جلسة مركزية وتفويض سابق يبادل الرمز بسلاسة؛ وإلا يعود فورًا إلى حالة الخروج (دون مقاطعة المستخدم).
completeCallback() يحلّل النتيجة في صفحة الاستدعاء: عند النجاح يعيد { code, codeVerifier }، وعند الفشل/الإلغاء يعيد { error }.
logoutEverywhere(returnTo?) يُنهي الجلسة المركزية ويسجّل الخروج بالتتابع من كل منتجات الحزمة، ثم يعود إلى returnTo.
تريد رؤيته عمليًا أولًا؟