انتقل إلى المحتوى الرئيسي

المصادقة متعددة العوامل (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/mfa10 رموز طوارئ أحادية الاستخدام تُنشأ أثناء إعداد 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": []
}
الحقلالوصف
secretTOTP secret بترميز Base32. أدخله يدويًا في تطبيق المصادقة إذا فشل مسح رمز QR
qrCodeUrlصورة PNG بترميز Base64 لرمز QR. اعرضها في واجهتك ليمسحها المستخدم

المستخدم يمسح رمز QR بتطبيق المصادقة. التطبيق يولّد رمز جديد من 6 أرقام كل 30 ثانية.

TOTP Parameters:

المعاملالقيمة
AlgorithmSHA1
Digits6
Period30 ثانية
Skewنافذة واحدة (±30 ثانية)

الخطوة 2 — التحقق وتفعيل TOTP

بعد أن يمسح المستخدم رمز QR، اطلب منه إدخال أول رمز لتأكيد نجاح الإعداد.

POST /api/v1/auth/mfa/verify-setup

Header مطلوب: Authorization: Bearer <accessToken>

{
"secret": "JBSWY3DPEHPK3PXP",
"code": "482031"
}
الحقلالنوعمطلوبالوصف
secretstringنعمالـ Secret الذي أُعيد من /mfa/setup
codestringنعمرمز 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:

  1. يجب التواصل مع مسؤول المستفيد.
  2. يمكن للمسؤول تعطيل MFA للمستخدم عبر لوحة تحكم المسؤول أو Admin API (POST /api/v1/users/&#123;id&#125;/unlock).
  3. بعد أن يُعيد المسؤول تعيين 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 StatusError Codeالسبب
400VALIDATION_ERRORmfaToken أو code أو secret أو password ناقص
401UNAUTHORIZEDرمز TOTP غير صالح أو منتهي
401UNAUTHORIZEDMFA Token منتهي الصلاحية (نافذة 5 دقائق)
401UNAUTHORIZEDBackup Code مستخدَم أو غير صالح
409CONFLICTMFA مفعّلة أصلاً عند استدعاء setup

الخطوات التالية