المصادقة متعددة العوامل (MFA)
Ithbat IAM يدعم عدة أساليب للعامل الثاني، يمكنك فرضها على مستوى المستفيد أو تهيئتها لكل مستخدم. هذا الدليل يغطي TOTP (تطبيقات المصادقة) و SMS OTP و Backup Codes — بما في ذلك مسار تسجيل الدخول الكامل ذو الخطوتين.
الأساليب المدعومة
| الأسلوب | Endpoint prefix | الوصف |
|---|---|---|
| TOTP | /api/v1/auth/mfa | كلمات مرور لمرة واحدة مبنية على الوقت عبر أي TOTP app (Google Authenticator, Authy, 1Password) |
| SMS OTP | /api/v1/auth/mfa/sms | رمز 6 أرقام عبر SMS (feature flag: mfa_sms) |
| Backup Codes | /api/v1/auth/mfa | 10 رموز طوارئ أحادية الاستخدام تُنشأ أثناء إعداد TOTP |
WebAuthn (Passkeys ومفاتيح الأمان) مدعوم كعامل ثانٍ وموثّق بشكل منفصل في دليل WebAuthn.
مسار تسجيل الدخول ذو الخطوتين
إذا كانت MFA مفعّلة عند المستخدم، يُعيد الـ Login API رسالة MFA Challenge بدلًا من الـ Tokens:
{
"mfaRequired": true,
"mfaToken": "mfa_challenge_abc123..."
}
صلاحية الـ mfaToken هي 5 دقائق. يجب استبداله بـ Session كاملة عبر إكمال MFA Challenge.
sequenceDiagram
participant User
participant App as Your App
participant Ithbat as Ithbat IAM
User->>App: Email + password
App->>Ithbat: POST /api/v1/auth/login
Ithbat-->>App: { mfaRequired: true, mfaToken: "..." }
App-->>User: Prompt for TOTP code
User->>App: Enter 6-digit TOTP code
App->>Ithbat: POST /api/v1/auth/mfa/verify { mfaToken, code }
Ithbat->>Ithbat: Validate TOTP code
Ithbat-->>App: { accessToken, refreshToken, idToken, user }
App-->>User: Signed in
إعداد TOTP
إعداد TOTP عملية من خطوتين: توليد الـ secret، ثم التحقق من رمز من تطبيق المصادقة لتأكيد أن الإعداد صحيح.
الخطوة 1 — توليد TOTP Secret
POST /api/v1/auth/mfa/setup
Header مطلوب: Authorization: Bearer <accessToken>
لا يتطلب request body.
الـ Response — 200 OK
{
"secret": "JBSWY3DPEHPK3PXP",
"qrCodeUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA...",
"backupCodes": []
}
| الحقل | الوصف |
|---|---|
secret | TOTP secret بترميز Base32. أدخله يدويًا في تطبيق المصادقة إذا فشل مسح رمز QR |
qrCodeUrl | صورة PNG بترميز Base64 لرمز QR. اعرضها في واجهتك ليمسحها المستخدم |
المستخدم يمسح رمز QR بتطبيق المصادقة. التطبيق يولّد رمز جديد من 6 أرقام كل 30 ثانية.
TOTP Parameters:
| المعامل | القيمة |
|---|---|
| Algorithm | SHA1 |
| Digits | 6 |
| Period | 30 ثانية |
| Skew | نافذة واحدة (±30 ثانية) |
الخطوة 2 — التحقق وتفعيل TOTP
بعد أن يمسح المستخدم رمز QR، اطلب منه إدخال أول رمز لتأكيد نجاح الإعداد.
POST /api/v1/auth/mfa/verify-setup
Header مطلوب: Authorization: Bearer <accessToken>
{
"secret": "JBSWY3DPEHPK3PXP",
"code": "482031"
}
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
secret | string | نعم | الـ Secret الذي أُعيد من /mfa/setup |
code | string | نعم | رمز TOTP الحالي من تطبيق المصادقة |
الـ Response — 200 OK
{
"backupCodes": [
"A1B2C3D4",
"E5F6G7H8",
"I9J0K1L2",
"M3N4O5P6",
"Q7R8S9T0",
"U1V2W3X4",
"Y5Z6A7B8",
"C9D0E1F2",
"G3H4I5J6",
"K7L8M9N0"
],
"message": "MFA enabled successfully. Save your backup codes in a secure location."
}
الـ Backup Codes تظهر مرة واحدة فقط، فور تفعيل TOTP. إذا فقدها المستخدم، يجب عليه إعادة إنشائها (مما يلغي جميع الرموز السابقة). احفظها في مكان آمن.
التحقق من MFA أثناء تسجيل الدخول (TOTP)
POST /api/v1/auth/mfa/verify
هذا الـ Endpoint عام (بدون Authorization Header). يستخدم mfaToken من Login Response الأول.
{
"mfaToken": "mfa_challenge_abc123...",
"code": "482031"
}
الـ Response — 200 OK
{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
"idToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 3600,
"user": {
"id": "usr_01J8X...",
"tenantId": "ten_01J8X...",
"email": "[email protected]",
"displayName": "Sara Al-Rashidi",
"roles": ["member"],
"permissions": ["profile:read"]
}
}
Backup Codes
استخدام Backup Code أثناء تسجيل الدخول
POST /api/v1/auth/mfa/verify-backup
{
"mfaToken": "mfa_challenge_abc123...",
"code": "A1B2C3D4"
}
إذا نجح، الـ Backup Code يُستهلك نهائيًا والـ Response نفس Token Response الكامل مثل MFA verify العادي. كل Backup Code يُستخدم مرة واحدة فقط.
الـ Response — 200 OK
نفس TOTP verify Response فوق.
إعادة إنشاء Backup Codes
إذا استنفد المستخدم أو فقد الـ Backup Codes، يمكنه توليد مجموعة جديدة. إعادة الإنشاء تتطلب رمز TOTP نشط لمنع إعادة إنشاء غير مصرّح بها.
POST /api/v1/auth/mfa/backup-codes
Header مطلوب: Authorization: Bearer <accessToken>
{
"code": "482031"
}
الـ Response — 200 OK
{
"backupCodes": [
"P1Q2R3S4",
"T5U6V7W8",
"..."
],
"message": "Backup codes regenerated successfully. Please save them in a secure location."
}
إعادة إنشاء Backup Codes تلغي كل الرموز المُنشأة سابقًا فورًا.
SMS OTP
MFA عبر SMS متاحة إذا feature flag mfa_sms مفعّل للمستفيد.
الإعداد — تسجيل رقم الهاتف
POST /api/v1/auth/mfa/sms/setup
Header مطلوب: Authorization: Bearer <accessToken>
{
"phoneNumber": "+966501234567"
}
يُرسل verification code على رقم الهاتف.
الـ Response — 200 OK
{
"message": "Verification code sent to your phone number. Please verify to enable SMS MFA."
}
الإعداد — التحقق من رقم الهاتف
POST /api/v1/auth/mfa/sms/verify-setup
Header مطلوب: Authorization: Bearer <accessToken>
{
"code": "847291"
}
الـ Response — 200 OK
{
"message": "SMS MFA has been enabled successfully."
}
إرسال SMS Code أثناء تسجيل الدخول
إذا مستخدم مفعّل لديه SMS MFA سجل دخول، وبعد ما Login الأول رجع mfaRequired: true، تطبيقك يرسل SMS OTP Request.
POST /api/v1/auth/mfa/sms/send
Header مطلوب: Authorization: Bearer <accessToken>
{
"phoneNumber": "+966501234567"
}
الـ Response — 200 OK
{
"message": "Verification code sent successfully."
}
التحقق من SMS Code أثناء تسجيل الدخول
POST /api/v1/auth/mfa/sms/verify
هذا الـ Endpoint عام (يستخدم mfaToken، ليس Access Token).
{
"mfaToken": "mfa_challenge_abc123...",
"code": "847291"
}
إذا نجح، يرجع Token Response الكامل (نفس TOTP verify).
تعطيل SMS MFA
POST /api/v1/auth/mfa/sms/disable
Header مطلوب: Authorization: Bearer <accessToken>
ما تحتاج request body.
الـ Response — 200 OK
{
"message": "SMS MFA has been disabled successfully."
}
تعطيل TOTP MFA
تعطيل TOTP يتطلب كلمة المرور الحالية ورمز TOTP صالح.
POST /api/v1/auth/mfa/disable
Header مطلوب: Authorization: Bearer <accessToken>
{
"password": "SecurePass123!",
"code": "482031"
}
الـ Response — 200 OK
{
"message": "MFA has been disabled successfully"
}
الاسترداد عند فقدان الجهاز
إذا فقد المستخدم جهاز المصادقة وليس لديه Backup Codes:
- يجب التواصل مع مسؤول المستفيد.
- يمكن للمسؤول تعطيل MFA للمستخدم عبر لوحة تحكم المسؤول أو Admin API (
POST /api/v1/users/{id}/unlock). - بعد أن يُعيد المسؤول تعيين MFA، يسجّل المستخدم الدخول بكلمة المرور فقط ويجب إعادة التسجيل في MFA فورًا.
شجّع المستخدمين على حفظ Backup Codes في password manager عند إعداد MFA لأول مرة. هذا يلغي الحاجة لتدخل المسؤول في أغلب حالات الفقدان.
أمثلة الكود
cURL — إعداد TOTP
# Step 1: Generate secret
curl -X POST https://api.ithbat.io/api/v1/auth/mfa/setup \
-H "Authorization: Bearer eyJhbGci..."
# Step 2: Verify and enable
curl -X POST https://api.ithbat.io/api/v1/auth/mfa/verify-setup \
-H "Authorization: Bearer eyJhbGci..." \
-H "Content-Type: application/json" \
-d '{"secret": "JBSWY3DPEHPK3PXP", "code": "482031"}'
cURL — التحقق من MFA أثناء تسجيل الدخول
curl -X POST https://api.ithbat.io/api/v1/auth/mfa/verify \
-H "Content-Type: application/json" \
-d '{"mfaToken": "mfa_challenge_abc123...", "code": "482031"}'
JavaScript SDK
import { IthbatSDK } from '@ithbatiam/sdk';
const ithbat = new IthbatSDK({ tenantId: 'ten_01J8X...' });
// === Setup Flow ===
// Step 1: Generate TOTP secret
const setup = await ithbat.mfa.setupTOTP();
// Show setup.qrCodeUrl as an <img> for the user to scan
// setup.secret is the manual entry fallback
// Step 2: User enters first code from their app
const result = await ithbat.mfa.verifyTOTPSetup({
secret: setup.secret,
code: '482031',
});
// result.backupCodes — show these once and tell user to save them
// === Login Flow with MFA ===
const loginResult = await ithbat.auth.login({
email: '[email protected]',
password: 'SecurePass123!',
});
if (loginResult.mfaRequired) {
// Prompt user for TOTP code
const mfaResult = await ithbat.mfa.verifyLogin({
mfaToken: loginResult.mfaToken,
code: '482031',
});
// mfaResult.accessToken — user is now fully authenticated
}
// === Backup Code Usage ===
const backupResult = await ithbat.mfa.verifyBackupCode({
mfaToken: loginResult.mfaToken,
code: 'A1B2C3D4',
});
// === Regenerate Backup Codes ===
const newCodes = await ithbat.mfa.regenerateBackupCodes({ code: '482031' });
// newCodes.backupCodes
معالجة الأخطاء
| HTTP Status | Error Code | السبب |
|---|---|---|
400 | VALIDATION_ERROR | mfaToken أو code أو secret أو password ناقص |
401 | UNAUTHORIZED | رمز TOTP غير صالح أو منتهي |
401 | UNAUTHORIZED | MFA Token منتهي الصلاحية (نافذة 5 دقائق) |
401 | UNAUTHORIZED | Backup Code مستخدَم أو غير صالح |
409 | CONFLICT | MFA مفعّلة أصلاً عند استدعاء setup |
الخطوات التالية
- WebAuthn / Passkeys — مصادقة مقاومة للتصيد عبر مفاتيح الأمان كعامل ثانٍ
- Token Lifecycle — الـ Sessions و Refresh Tokens بعد MFA login
- البريد وكلمة المرور — العامل الأول الذي يسبق MFA