> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# البدء السريع بـ JavaScript للمصادقة

> اربط تطبيق المصادقة المفعّل في Didit بتسجيل الدخول المستضاف باستخدام PKCE، مع التحقق من رابط الاستدعاء والجلسة وتسجيل الخروج.

> [!WARNING]
>
> المصادقة ميزة جديدة: استخدم مثال التدفق المستضاف هذا مع تطبيق فعّلت فيه المصادقة. حزمة `@didit-protocol/auth` غير منشورة بعد، وواجهة الحزمة أدناه معاينة وليست دليل بدء سريع قابلاً للتثبيت.

## إعداد تسجيل الدخول المستضاف

سجّل عنوان رابط الاستدعاء الدقيق وأصل الويب الخاص بك لتطبيق البيئة التجريبية. انسخ أصل تسجيل الدخول (`https://<slug>.sandbox.auth.didit.me`) من وحدة التحكم، كما هو موضح في [النظرة العامة](https://docs.didit.me/ar/authentication/overview.md). يستخدم هذا المثال واجهات التشفير في المتصفح ويتطلب HTTPS، أو localhost في البيئة التجريبية. راجع [التطوير المحلي](https://docs.didit.me/ar/authentication/overview.md#التطوير-المحلي) لمعرفة ما يجب تسجيله.

يملك التطبيق القيمة `state` ومُتحقّق PKCE. ويملك تسجيل الدخول المستضاف شاشات كلمة المرور والبريد الإلكتروني ومفتاح المرور والهاتف وتسجيل الدخول الموحد والمصادقة متعددة العوامل المطلوبة. لا يجب أن يوجد أي مفتاح API في هذا الكود.

```javascript auth.js theme={null}
// Replace both values with your registered application configuration.
const AUTH_BASE = "https://YOUR_SLUG.sandbox.auth.didit.me/";
const REDIRECT_URI = "https://YOUR_APP_ORIGIN/auth/callback";
const PENDING = "didit.auth.pending";
let tokens = null;

function base64url(bytes) {
  return btoa(String.fromCharCode(...bytes))
    .replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

export async function signIn() {
  const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
  const state = base64url(crypto.getRandomValues(new Uint8Array(32)));
  const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
  sessionStorage.setItem(PENDING, JSON.stringify({ verifier, state, startedAt: Date.now() }));
  const url = new URL("sign-in", AUTH_BASE);
  url.search = new URLSearchParams({
    redirect_uri: REDIRECT_URI,
    state,
    code_challenge: base64url(new Uint8Array(digest)),
    code_challenge_method: "S256",
  }).toString();
  window.location.assign(url.href);
}

export async function handleCallback() {
  const query = new URLSearchParams(window.location.search);
  const saved = sessionStorage.getItem(PENDING);
  sessionStorage.removeItem(PENDING);
  history.replaceState(null, "", window.location.pathname);
  if (!saved) throw new Error("Start sign-in again.");
  const pending = JSON.parse(saved);
  if (query.get("state") !== pending.state || Date.now() - pending.startedAt > 600000) {
    throw new Error("Invalid or expired sign-in. Start again.");
  }
  if (query.has("error") || !query.get("code")) throw new Error("Sign-in was not completed.");
  const response = await fetch(new URL("token/", AUTH_BASE), {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      grant_type: "authorization_code",
      code: query.get("code"),
      code_verifier: pending.verifier,
      redirect_uri: REDIRECT_URI,
    }),
  });
  if (!response.ok) throw new Error("Code exchange failed. Start sign-in again.");
  tokens = await response.json();
  return getSession();
}

export async function getSession() {
  if (!tokens) return null;
  const response = await fetch(new URL("session/", AUTH_BASE), {
    headers: { Authorization: `Bearer ${tokens.access_token}` },
    cache: "no-store",
  });
  if (!response.ok) {
    tokens = null;
    throw new Error("Session check failed. Sign in again.");
  }
  return response.json();
}

export async function signOut() {
  const current = tokens;
  tokens = null;
  if (!current) return;
  const response = await fetch(new URL("session/", AUTH_BASE), {
    method: "DELETE",
    headers: { Authorization: `Bearer ${current.access_token}` },
  });
  if (response.status !== 204) throw new Error("Local state cleared; server logout failed.");
}
```

استدعِ `signIn()` من زر تسجيل الدخول لديك. في صفحة رابط الاستدعاء المسجلة، استدعِ `handleCallback()` مرة واحدة، واعرض حالة تحميل، واعرض خطأه إن فشل. استخدم `getSession()` للحصول على المستخدم الحالي، و`signOut()` لتسجيل الخروج. تزيل دالة الاستدعاء الرمز من شريط العنوان قبل إرسال أي طلب.

يحتفظ هذا المثال المبسط برمز الوصول في الذاكرة، ويعيد تسجيل الدخول بعد إعادة تحميل الصفحة أو انتهاء صلاحية رمز الوصول. للجلسات الدائمة، استخدم الخادم الخلفي وملفات تعريف ارتباط آمنة، أو نفّذ [تدوير رمز التحديث](https://docs.didit.me/ar/authentication/tokens-and-jwks.md) بشكل متسلسل. لا تضع رمز التحديث أبدًا في الروابط أو السجلات. يتحكم فحص الجلسة في الواجهة الأمامية في العرض فقط، ويجب أن يتحقق الخادم الخلفي من هوية المستدعي في كل طلب محمي.

## معاينة إصدار SDK المصادقة

تعرض النواة المخطط لها `@didit-protocol/auth` الدوال `createDiditAuth({publishableKey})` و`signIn()` و`handleRedirectCallback()` و`getSession()` و`getToken()` و`onAuthStateChange` و`signOut()`، مع `vendorData` في الهوية. ومن المخطط أن تضيف إشارات الجهاز التلقائية ونقطة دخول من جهة الخادم تتضمن `verifyToken()`.

المفتاح القابل للنشر هو `pk_live_` (لتطبيق الإنتاج) أو `pk_test_` (لتطبيق البيئة التجريبية)، متبوعًا بترميز base64url بدون حشو لأصل تطبيقك. ترسل الحزمة طلبات الواجهة البرمجية إلى هذا الأصل. المفتاح عام: فهو يحدد التطبيق، وليس سرًا.

### رفع مستوى التحقق وإعادة المصادقة في المعاينة

* `stepUp({ action, amount?, currency?, redirectUri? })` يستدعي `POST step-up/` في تطبيقك للسؤال عما إذا كان `action` يحتاج إلى التحقق من الهوية. قيمة `action` هي `payout` أو `bank` أو `contact`، ويحتاج payout إلى `amount`. عند انطباق إحدى قواعد رفع المستوى لديك، تنتقل الدالة إلى صفحة التحقق التي تعيدها Didit.
* `handleStepUpCallback(url?)` يعمل على الصفحة التي يعود إليها الشخص. يقرأ `?step_up=<id>`، ويزيله من شريط العنوان، ثم يقرأ النتيجة باستخدام `GET step-up/{id}/`.
* `reauthenticate({ method? })` يعيد تسجيل دخول الشخص نفسه، إما في الصفحة المستضافة (`method: "redirect"`، وهي الافتراضية) أو بمفتاح مرور (`method: "passkey"`، ولا يعمل إلا على نطاق تسجيل دخول Didit الخاص بتطبيقك). بعد الصفحة المستضافة، أكمله باستدعاء `handleRedirectCallback()`. إذا أكمله شخص آخر، فإنه يُرفض بالخطأ `step_up_user_mismatch` وتبقى الجلسة الأصلية كما هي.

تُعيد الطريقتان الخاصتان برفع المستوى نتيجة تحتوي على `{ id, status, approved, rule, method }`، حيث تكون قيمة `status` إحدى القيم `not_required` أو `pending` أو `approved` أو `review` أو `declined` أو `expired`. القيمة الافتراضية لـ `redirectUri` هي عنوان إعادة التوجيه الخاص بالعميل، ويجب أن يطابق تمامًا أحد عناوين إعادة التوجيه المسجلة في تطبيقك. عندما يكون التحقق مطلوبًا، ترفض Didit أي عنوان آخر.

قبل أن يتصرف الخادم الخلفي بناءً على رفع المستوى، يقرأ الخادم الخلفي عملية رفع المستوى مرة أخرى باستخدام `GET step-up/{id}/` ورمز الوصول الخاص بالشخص، لأن النتيجة التي يبلغ عنها المتصفح قد يجري تغييرها.

قد يرد تسجيل الدخول بلا واجهة أيضًا بالقيمة `protection_required` عندما تضع قواعد الحماية في تطبيقك علامة عليه. عندها ينهي الشخص العملية بالرمز الذي أرسلته Didit إلى بريده الإلكتروني (`protection.verify({ code })`) أو بمفتاح المرور (`protection.passkey()`)، وتسرد `methods` أيًا من الطريقتين يمكنه استخدامهما.

لا تثبّت نسخة مُخمَّنة، ولا تكتب كودًا يعتمد على خيارات استدعاء مُخمَّنة لردّ الاتصال. أكّد ما تصدّره الحزمة المنشورة وجهة الإصدار وإعدادات المفتاح قبل استبدال المثال المستضاف. ستعتمد طرق كلمة المرور ورمز البريد الإلكتروني والرابط السحري ومفتاح المرور والهاتف والمصادقة متعددة العوامل وتسجيل الدخول عبر الحسابات الاجتماعية ورفع المستوى وطرق الوكلاء على الواجهة البرمجية المدعومة في ذلك الإصدار.

## إضافة منتجات أخرى

يتحقق الخادم الخلفي من رمز الوصول (انظر [الرموز وJWKS](https://docs.didit.me/ar/authentication/tokens-and-jwks.md)) ويقرأ قيمة `vendor_data` الخاصة به. استخدم هذه القيمة نفسها بوصفها `vendor_data` عند [إنشاء جلسة تحقق](https://docs.didit.me/ar/sessions-api/create-session.md) أو [إصدار token للمعاملة](https://docs.didit.me/ar/transaction-monitoring/sdk-transaction-submission.md). لا يعني نجاح تسجيل الدخول أن أيًا من المنتجين وافق على المستخدم.

قبل الإطلاق، اختبر التسجيل، وتسجيل الدخول للمستخدم العائد، والإلغاء، وعدم تطابق state، وإعادة استخدام الرمز، ونسيان كلمة المرور، والمصادقة متعددة العوامل، وانتهاء الصلاحية، وتسجيل الخروج، وذلك على تطبيق البيئة التجريبية المفعّل لديك.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.