تنفيذ حلّ للتحقّق من الهوية باستخدام FedCM من جهة موفّر الهوية

يتضمّن تنفيذ FedCM عدة خطوات أساسيه لكل من موفِّر الهوية (IdP) والطرف الموثوق (RP). راجِع مستندات FedCM للتعرّف على كيفية تنفيذها من جانب موفّر المحتوى.

على IdPs إكمال الخطوات التالية لتنفيذ FedCM:

إنشاء ملف well-known

لمنع أدوات التتبّع من إساءة استخدام واجهة برمجة التطبيقات، يجب عرض ملف well-known من /.well-known/web-identity في النطاق العلوي للدومين (eTLD)+1 في موفِّر الهوية.

يمكن أن يتضمّن الملف المعروف السمات التالية:

الموقع مطلوب الوصف
provider_urls مطلوب صفيف لمسارات ملفات إعداد موفِّر الهوية يتم تجاهلها (ولكنها لا تزال مطلوبة) في حال تحديد accounts_endpoint وlogin_url.
accounts_endpoint يُنصح باستخدام هذا الإجراء، ويتطلب login_url
عنوان URL لنقطة نهاية الحسابات يتيح ذلك إمكانية استخدام إعدادات متعددة، ما دام كل ملف إعداد يستخدم عنوانَي URL login_url وaccounts_endpoint نفسيهما.

ملاحظة: تتوفّر المَعلمة اعتبارًا من الإصدار 132 من Chrome.
login_url يُنصح به، ويتطلب accounts_endpoint عنوان URL لصفحة تسجيل الدخول للمستخدم لتسجيل الدخول إلى موفِّر الهوية يتيح ذلك إمكانية استخدام إعدادات متعدّدة، ما دام كل ملف إعداد يستخدم login_url وaccounts_endpoint نفسهما.

ملاحظة: تتوفّر المَعلمة اعتبارًا من الإصدار 132 من Chrome والإصدارات الأحدث.

على سبيل المثال، إذا كانت نقاط نهاية موفِّر الهوية معروضة ضمن https://accounts.idp.example/، يجب أن تعرض ملفًا معروفًا في https://idp.example/.well-known/web-identity بالإضافة إلى ملف إعدادات موفِّر هوية. في ما يلي مثال على محتوى ملف معروف:

  {
    "provider_urls": ["https://accounts.idp.example/config.json"]
  }

يمكن لموفِّري الهوية استيعاب ملفات إعدادات متعددة لموفِّر الهوية، وذلك من خلال تحديد accounts_endpoint وlogin_url في ملف well-known.
يمكن أن تكون هذه الميزة مفيدة في الحالات التالية:

  • يجب أن يتيح موفِّر الهوية إعدادات مختلفة متعددة للاختبار والإصدار العلني.
  • يجب أن يتيح موفِّر الهوية إعدادات مختلفة لكل منطقة (على سبيل المثال، eu-idp.example وus-idp.example).

لتتوافق مع الإعدادات المتعدّدة (على سبيل المثال، للتمييز بين ملف اختبار وملف الإصدار العلني)، يجب أن يحدّد موفِّر الهوية accounts_endpoint و login_url:

  {
    // This property is required, but will be ignored when IdP supports
    // multiple configs (when `accounts_endpoint` and `login_url` are
    // specified), as long as `accounts_endpoint` and `login_url` in
    // that config file match those in the well-known file.
    "provider_urls": [ "https://idp.example/fedcm.json" ],

    // Specify accounts_endpoint and login_url properties to support
    // multiple config files.
    // Note: The accounts_endpoint and login_url must be identical
    // across all config files. Otherwise,
    // the configurations won't be supported.
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }

إنشاء ملف إعدادات موفِّر الهوية ونقاط النهاية

يقدّم ملف إعدادات مزوّد الهوية قائمة بنقاط النهاية المطلوبة للمتصفح. يجب أن تستضيف منصّات إدارة الهوية ملفًا واحدًا أو عدة ملفات إعدادات ونقاط النهاية وعناوين URL المطلوبة. ويجب عرض كل الاستجابات بتنسيق JSON باستخدام نوع المحتوى application/json.

يتم تحديد عنوان URL لملف الإعدادات من خلال القيم المقدَّمة لاستدعاء navigator.credentials.get() الذي يتم تنفيذه على RP.

  const credential = await navigator.credentials.get({
    identity: {
      context: 'signup',
      providers: [{
        configURL: 'https://accounts.idp.example/config.json',
        clientId: '********',
        nonce: '******'
      }]
    }
  });
  const { token } = credential;

سيُرسِل مقدّم الخدمة عنوان URL لملف الإعداد إلى طلب FedCM API للسماح للمستخدم بالتسجيل:

  // Executed on RP's side:
  const credential = await navigator.credentials.get({
    identity: {
      context: 'signup',
      providers: [{
        // To allow users to sign in with an IdP using FedCM, RP specifies the IdP's config file URL:
        configURL: 'https://accounts.idp.example/fedcm.json',
        clientId: '********',
  });
  const { token } = credential;

سيجلب المتصفّح ملف الإعدادات باستخدام طلب GET بدون عنوان Origin أو عنوان Referer. لا يتضمّن الطلب ملفات تعريف الارتباط ولا يلي عمليات إعادة التوجيه. ويؤدي ذلك إلى منع موفِّر الهوية بشكل فعّال من معرفة الجهة التي قدّمت الطلب ووحدة التحكّم في الوصول التي تحاول الاتصال. على سبيل المثال:

  GET /config.json HTTP/1.1
  Host: accounts.idp.example
  Accept: application/json
  Sec-Fetch-Dest: webidentity

يجب أن ينفّذ موفّر الهوية نقطة نهاية إعدادات تستجيب بتنسيق JSON. يتضمّن ملف JSON السمات التالية:

الموقع الوصف
accounts_endpoint (مطلوب) عنوان URL لنقطة نهاية الحسابات
accounts.include (اختياري) سلسلة تصنيف الحساب المخصّصة التي تحدّد الحسابات التي يجب عرضها عند استخدام ملف الإعدادات هذا، على سبيل المثال: "accounts": {"include": "developer"}.
يمكن لموفِّر الهوية تنفيذ تصنيف الحسابات المخصّص على النحو التالي:

على سبيل المثال، ينفِّذ موفِّر الهوية "https://idp.example/developer-config.json" ملف الإعداد مع تحديد "accounts": {"include": "developer"}. يضع موفِّر الهوية أيضًا تصنيف "developer" على بعض الحسابات باستخدام المَعلمة labels في نقطة نهاية الحسابات. عندما يطلب مقدّم المحتوى navigator.credentials.get() مع تحديد ملف الإعداد "https://idp.example/developer-config.json"، لن يتم عرض سوى الحسابات التي تحمل التصنيف "developer".

ملاحظة: تتوفّر تصنيفات الحسابات المخصّصة في الإصدار 132 من Chrome.
client_metadata_endpoint (اختياري) عنوان URL لنقطة نهاية البيانات الوصفية للعميل
id_assertion_endpoint (مطلوب) عنوان URL لنقطة نهاية بيان الهوية.
disconnect (اختياري) عنوان URL لنقطة نهاية إلغاء الاتصال
login_url (مطلوب) عنوان URL لصفحة تسجيل الدخول للمستخدم لتسجيل الدخول إلى موفِّر الهوية
branding (اختياري) عنصر يحتوي على خيارات مختلفة للعلامة التجارية
branding.background_color (اختياري) خيار وضع العلامة التجارية الذي يضبط لون خلفية الزر "متابعة باسم حساب..." استخدِم بنية CSS ذات الصلة، وهي hex-color أو hsl() أو rgb() أو named-color.
branding.color (اختياري) خيار وضع العلامة التجارية الذي يحدّد لون نص الزر "متابعة باسم حساب..." استخدِم بنية CSS ذات الصلة، وهي hex-color أو hsl() أو rgb() أو named-color.
branding.icons (اختياري) مصفوفة من عناصر الرموز يتم عرض هذه الرموز في مربّع حوار تسجيل الدخول. يحتوي عنصر الرمز على مَعلمتَين:
  • url (سمة مطلوبة): عنوان URL لصورة الرمز. لا تتوفّر إمكانية استخدام صور SVG.
  • size (اختياري): أبعاد الرمز، يفترض التطبيق أنّها مربّعة وبدرجة دقة واحدة. يجب أن يكون هذا الرقم أكبر من أو يساوي 25 بكسل في الوضع التلقائي، وأكبر من أو يساوي 40 بكسل في الوضع النشط.
modes عنصر يحتوي على مواصفات حول كيفية عرض واجهة مستخدم FedCM في أوضاع مختلفة:
  • active
  • passive
modes.active عنصر يحتوي على سمات تسمح بتخصيص سلوك FedCM في وضع معيّن يمكن أن يحتوي كلّ من modes.active وmodes.passive على المَعلمة التالية:
  • supports_use_other_account: قيمة منطقية تحدّد ما إذا كان بإمكان المستخدم تسجيل الدخول باستخدام حساب مختلف عن الحساب الذي سجّل الدخول إليه حاليًا (إذا كان موفِّر خدمة المصادقة يتوافق مع حسابات متعدّدة).

ملاحظة: تتوفّر ميزة "استخدام حساب آخر" والوضع النشط من الإصدار 132 من Chrome.
modes.passive

في ما يلي مثال على نص الاستجابة من موفّر الهوية:

  {
    "accounts_endpoint": "/accounts.example",
    "client_metadata_endpoint": "/client_metadata.example",
    "id_assertion_endpoint": "/assertion.example",
    "disconnect_endpoint": "/disconnect.example",
    "login_url": "/login",
    // When RPs use this config file, only those accounts will be
    //returned that include `developer` label in the accounts endpoint.
    "accounts": {"include": "developer"},
    "modes": {
        "active": {
          "supports_use_other_account": true,
        }
    },
    "branding": {
      "background_color": "green",
      "color": "#FFEEAA",
      "icons": [{
        "url": "https://idp.example/icon.ico",
        "size": 25
      }]
    }
  }

بعد أن يجلب المتصفّح ملف الإعدادات، يرسل طلبات لاحقة إلى نقاط نهاية IDEP:

نقاط نهاية موفِّر الهوية
نقاط نهاية موفِّر الهوية (IdP)

استخدام حساب آخر

يمكن للمستخدمين التبديل إلى حساب مختلف عن الحساب الذي سجّلوا الدخول باستخدامه حاليًا، إذا كان موفِّر خدمة المصادقة يتوافق مع حسابات متعدّدة أو استبدال الادّعاء الحالي.

لتمكين المستخدم من اختيار حسابات أخرى، يجب أن يحدِّد موفِّر الهوية هذه الميزة في ملف الإعدادات:

  {
    "accounts_endpoint" : "/accounts.example",
    "modes": {
      "active": {
        // Allow the user to choose other account (false by default)
        "supports_use_other_account": true
      }
      // "passive" mode can be configured separately
    }
  }

نقطة نهاية الحسابات

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

يُرسِل المتصفّح طلب GET يتضمّن ملفات تعريف ارتباط تتضمّن SameSite=None، ولكن بدون مَعلمة client_id أو عنوان Origin أو عنوان Referer. ويؤدي ذلك بفعال إلى منع موفِّر الهوية من معرفة موفِّر الخدمات الذي يحاول المستخدم تسجيل الدخول إليه. على سبيل المثال:

  GET /accounts.example HTTP/1.1
  Host: accounts.idp.example
  Accept: application/json
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

عند تلقّي الطلب، يجب أن ينفّذ الخادم ما يلي:

  1. تأكَّد من أنّ الطلب يحتوي على عنوان Sec-Fetch-Dest: webidentity HTTP.
  2. مطابقة ملفات تعريف الارتباط الخاصة بالجلسة مع أرقام تعريف الحسابات التي سبق أن سجّلت الدخول إليها
  3. يُرجى الردّ مع تضمين قائمة الحسابات.

يتوقّع المتصفّح استجابة JSON تتضمّن سمة accounts مع صفيف من معلومات الحساب التي تتضمّن السمات التالية:

الموقع الوصف
id (مطلوب) المعرّف الفريد للمستخدم
name (مطلوب) الاسم الأول واسم العائلة للمستخدم
email (مطلوب) عنوان البريد الإلكتروني للمستخدم.
given_name (اختياري) الاسم الأول للمستخدم.
picture (اختياري) عنوان URL لصورة رمز المستخدم
approved_clients (اختياري) صفيف من أرقام تعريف عملاء RP التي سجّل المستخدم نفسه بها
login_hints (اختياري) مصفوفة من جميع أنواع الفلاتر الممكنة التي يتيحها موفِّر الهوية لتحديد حساب يمكن لـ RP استدعاء navigator.credentials.get() باستخدام الموقع loginHint لإظهار الحساب المحدّد بشكل انتقائي.
domain_hints (اختياري) صفيف يضمّ جميع النطاقات المرتبطة بالحساب يمكن لـ RP الاتصال بـ navigator.credentials.get() باستخدام موقع domainHint لفلترة الحسابات.
labels (اختياري) صفيف من تصنيفات الحساب المخصّصة التي يرتبط بها حساب معيّن
يمكن لموفِّر الهوية (IdP) تنفيذ تصنيف الحسابات المخصّص على النحو التالي:
  • حدِّد تصنيفات الحسابات في نقطة نهاية الحسابات (باستخدام مَعلمة labels هذه).
  • أنشئ ملف إعدادات لكل تصنيف محدّد.

على سبيل المثال، ينفِّذ موفِّر الهوية https://idp.example/developer-config.json ملف الإعداد مع تحديد "accounts": {"include": "developer"}. يضع موفِّر الهوية أيضًا تصنيف "developer" على بعض الحسابات باستخدام المَعلمة labels في نقطة نهاية حسابات. عندما يطلب مقدّم المحتوى navigator.credentials.get() مع تحديد ملف الإعداد https://idp.example/developer-config.json، لن يتم عرض سوى الحسابات التي تحمل التصنيف "developer".

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

ملاحظة: تتوفّر تصنيفات الحسابات المخصّصة اعتبارًا من الإصدار 132 من Chrome.

مثال على نص الاستجابة:

  {
    "accounts": [{
      "id": "1234",
      "given_name": "John",
      "name": "John Doe",
      "email": "john_doe@idp.example",
      "picture": "https://idp.example/profile/123",
      // Ids of those RPs where this account can be used
      "approved_clients": ["123", "456", "789"],
      // This account has 'login_hints`. When an RP calls `navigator.credentials.get()`
      // with a `loginHint` value specified, for example, `exampleHint`, only those
      // accounts will be shown to the user whose 'login_hints' array contains the `exampleHint`.
      "login_hints": ["demo1", "exampleHint"],
      // This account is labelled. IdP can implement a specific config file for a
      // label, for example, `https://idp.example/developer-config.json`. Like that
      // RPs can filter out accounts by calling `navigator.credentials.get()` with
      // `https://idp.example/developer-config.json` config file.
      "labels": ["hr", "developer"]
    }, {
      "id": "5678",
      "given_name": "Johnny",
      "name": "Johnny",
      "email": "johnny@idp.example",
      "picture": "https://idp.example/profile/456",
      "approved_clients": ["abc", "def", "ghi"],
      "login_hints": ["demo2"],
      "domain_hints": ["@domain.example"]
    }]
  }

إذا لم يسجّل المستخدم الدخول، يجب الردّ عليه برمز HTTP 401 (غير مصرّح به).

يستخدم المتصفّح قائمة الحسابات التي تم عرضها ولن تكون متاحة لمسؤول المراجعة.

نقطة نهاية بيان الهوية

تعرض نقطة نهاية بيان الهوية لموفِّر الهوية بيانًا للمستخدم الذي سجّل الدخول. عندما يسجّل المستخدم الدخول إلى موقع إلكتروني تابع لخدمة مقارنة الأسعار باستخدام navigator.credentials.get() طلب، يُرسِل المتصفّح طلب POST مع ملفات تعريف الارتباط التي تحتوي على SameSite=None ونوع محتوى هو application/x-www-form-urlencoded إلى نقطة النهاية هذه مع المعلومات التالية:

الموقع الوصف
client_id (مطلوب) معرّف العميل لمسؤول المعالجة
account_id (مطلوب) المعرّف الفريد للمستخدِم الذي سجّل الدخول.
disclosure_text_shown تؤدي إلى ظهور سلسلة من "true" أو "false" (بدلاً من قيمة منطقية). تكون النتيجة "false" في الحالات التالية:
  • إذا لم يتم عرض نص الإفصاح لأنّه تم تضمين رقم تعريف العميل الخاص بمسؤول المعالجة في قائمة approved_clients للردّ من نقطة نهاية الحسابات.
  • إذا لم يتم عرض نص بيان الإفصاح لأنّ المتصفّح رصد لحظة اشتراك في الماضي في غياب approved_clients.
  • إذا كانت المَعلمة fields لا تتضمّن حقلًا واحدًا أو أكثر من الحقول الثلاثة ("الاسم" و"البريد الإلكتروني" و "الصورة")، على سبيل المثال، fields=[ ] أو fields=['name', 'picture']. ويُعدّ ذلك ضروريًا للتوافق مع الإصدارات القديمة من عمليات تنفيذ موفِّري خدمات التعريف التي تتوقّع أن تتضمّن سلسلة بيان الإفصاح دائمًا جميع الحقول الثلاثة.
is_auto_selected في حال تنفيذ إعادة المصادقة التلقائية على نقطة الربط، يشير is_auto_selected إلى "true". بخلاف ذلك، "false". ويساعد ذلك في توفير المزيد من الميزات المتعلّقة بالأمان. على سبيل المثال، قد يفضّل بعض المستخدمين مستوى أمان أعلى يتطلّب توسّط المستخدم بشكل صريح في المصادقة. إذا تلقّى موفّر الهوية طلب رمز مميّز بدون هذا التوسّط، يمكنه معالجة الطلب بشكل مختلف. على سبيل المثال، يمكنك عرض رمز خطأ ليتمكّن مقدّم المحتوى من طلب بيانات من واجهة برمجة التطبيقات FedCM مرة أخرى باستخدام mediation: required.
fields (اختياري) صفيف من السلاسل التي تحدّد معلومات المستخدم ("الاسم" و"البريد الإلكتروني" و"الصورة") التي يحتاج إليها مقدّم طلب الاعتماد من موفّر الهوية لمشاركتها معه.
سيرسل المتصفّح fields وdisclosure_text_shown وdisclosure_shown_for مع إدراج الحقول المحدّدة في طلب POST، كما هو موضّح في المثال التالي.

ملاحظة: تتوفّر المَعلمة Fields في الإصدار 132 من Chrome.
params (اختياري) أيّ عنصر JSON صالح يسمح بتحديد مَعلمات مخصّصة إضافية للمفتاح والقيمة، على سبيل المثال:
  • scope: قيمة سلسلة تحتوي على أذونات إضافية يحتاج إليها مقدّم الطلب، على سبيل المثال "drive.readonly calendar.readonly"
  • nonce: سلسلة عشوائية يوفّرها مقدّم الخدمة لضمان إصدار الردّ لهذا الطلب المحدّد. منع هجمات إعادة التشغيل
  • مَعلمات مخصّصة أخرى للمفاتيح والقيم
عندما يُرسِل المتصفّح طلب POST، سيتم تسلسل قيمة params إلى تنسيق JSON ثم ترميزها باستخدام النسبة المئوية.

ملاحظة: تتوفّر واجهة برمجة التطبيقات Parameters API في الإصدار 132 من Chrome والإصدارات الأحدث.

مثال على عنوان HTTP:

  POST /assertion.example HTTP/1.1
  Host: accounts.idp.example
  Origin: https://rp.example/
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

  // disclosure_text_shown is set to 'false', as the 'name' field value is missing in 'fields' array
  // params value is serialized to JSON and then percent-encoded.
  account_id=123&client_id=client1234&disclosure_text_shown=false&is_auto_selected=true&params=%22%7B%5C%22nonce%5C%22%3A%5C%22nonce-value%5C%22%7D%22.%0D%0A4&disclosure_text_shown=true&fields=email,picture&disclosure_shown_for=email,picture

عند تلقّي الطلب، يجب أن ينفّذ الخادم ما يلي:

  1. يجب الردّ على الطلب باستخدام مشاركة الموارد المتعدّدة المصادر (CORS).
  2. تأكَّد من أنّ الطلب يحتوي على عنوان Sec-Fetch-Dest: webidentity HTTP.
  3. قارِن عنوان Origin بمصدر RP الذي يحدّده العنصر client_id. رفض النموذج في حال عدم تطابقه
  4. قارِن account_id بمعرّف الحساب الذي سبق أن سجّلت الدخول إليه. رفضه إذا لم يتطابق
  5. يجب الردّ باستخدام رمز مميّز. في حال رفض الطلب، يمكنك الردّ بإرسال استجابة بالخطأ.

يمكن لموفّر خدمة المصادقة تحديد كيفية إصدار الرمز المميّز. بشكل عام، يتم التوقيع عليه باستخدام معلومات مثل رقم تعريف الحساب ورقم تعريف العميل ومصدر جهة الإصدار وعدد الطلبات غير المتكرّرة، لكي تتمكّن وحدة التحكّم في حدود الجلسة من التأكّد من أنّ الرمز المميّز أصلي.

يتوقّع المتصفّح استجابة JSON تتضمّن السمة التالية:

الموقع الوصف
token رمز المرور هو سلسلة تحتوي على إثباتات حول المصادقة.
continue_on عنوان URL لإعادة التوجيه الذي يتيح عملية تسجيل دخول متعددة الخطوات

يُرسِل المتصفّح الرمز المميّز الذي تم إرجاعه إلى مقدّم الخدمة لكي يتمكّن من إثبات صحة المصادقة.

  {
    // IdP can respond with a token to authenticate the user
    "token": "***********"
  }

ميزة "المتابعة على"

يمكن لموفِّر الهوية توفير عنوان URL لإعادة التوجيه في استجابة نقطة نهاية تأكيد رقم التعريف لتفعيل مسار تسجيل دخول متعدد الخطوات. يكون ذلك مفيدًا عندما يحتاج موفِّر الهوية إلى طلب معلومات أو أذونات إضافية، على سبيل المثال:

  • إذن بالوصول إلى موارد المستخدم من جهة الخادم
  • إثبات أنّ معلومات الاتصال محدّثة
  • أدوات رقابة الأهل

يمكن أن تُرجع نقطة نهاية بيان الهوية عنصرًا من النوع continue_on يتضمّن مسارًا مطلقًا أو نسبيًا إلى نقطة نهاية بيان الهوية.

  {
    // In the id_assertion_endpoint, instead of returning a typical
    // "token" response, the IdP decides that it needs the user to
    // continue on a popup window:
    "continue_on": "https://idp.example/continue_on_url"
  }

إذا كان الردّ يحتوي على المَعلمة continue_on، يتم فتح نافذة منبثقة جديدة وتوجيه المستخدِم إلى المسار المحدّد. بعد تفاعل المستخدم مع صفحة continue_on، يجب أن يتصل موفِّر الهويةIdentityProvider.resolve() مع تمرير الرمز المميّز كوسيطة حتى يمكن حلّ الوعد منnavigator.credentials.get() المكالمة الأصلية:

  document.getElementById('example-button').addEventListener('click', async () => {
    let accessToken = await fetch('/generate_access_token.cgi');
    // Closes the window and resolves the promise (that is still hanging
    // in the relying party's renderer) with the value that is passed.
    IdentityProvider.resolve(accessToken);
  });

بعد ذلك، سيغلق المتصفّح النافذة المنبثقة تلقائيًا ويُعيد الرمز المميّز إلى مدعِّي واجهة برمجة التطبيقات. إنّ طلب IdentityProvider.resolve() لمرة واحدة هو الطريقة الوحيدة للتواصل بين النافذة الرئيسية (RP) والنافذة المنبثقة (IdP).
إذا رفض المستخدم الطلب، يمكن لموفِّر الهوية إغلاق النافذة من خلال استدعاء IdentityProvider.close().

  IdentityProvider.close();

تتطلّب واجهة برمجة التطبيقات Continuation API تفاعلًا صريحًا من المستخدِم (النقرات) لكي تعمل. في ما يلي كيفية عمل Continuation API مع أوضاع التوسّط المختلفة:

  • في الوضع التلقائي:
    • mediation: 'optional' (الإعداد التلقائي): لن تعمل واجهة برمجة التطبيقات Continuation API إلا باستخدام إيماءة المستخدم، مثل النقر على زر في الصفحة أو على واجهة مستخدم FedCM. عند بدء إعادة المصادقة التلقائية بدون لفتة من المستخدم، لا يتم فتح نافذة منبثقة ويتم رفض الوعد.
    • mediation: 'required': يطلب من المستخدم التفاعل دائمًا، لذا تعمل واجهة برمجة التطبيقات Continuation API دائمًا.
  • في الوضع النشط:
    • يجب دائمًا تفعيل المستخدم. أن تكون Continuation API متوافقة

إذا غيّر المستخدم حسابه في النافذة المنبثقة لأي سبب (على سبيل المثال، يقدّم موفِّر الهوية وظيفة "استخدام حساب آخر"، أو في حالات التفويض)، يأخذ أسلوب resolve وسيطة ثانية اختيارية تسمح بإجراء ما يلي:

  IdentityProvider.resolve(token, {accountId: '1234');

عرض ردّ يفيد بحدوث خطأ

يمكن أن يعرض id_assertion_endpoint أيضًا استجابة "خطأ" ، والتي تتضمّن حقلَين اختياريَين:

  • code: يمكن لموفِّر الهوية اختيار أحد الأخطاء المعروفة من قائمة أخطاء OAuth 2.0 المحدّدة (invalid_request وunauthorized_client وaccess_denied وserver_error وtemporarily_unavailable) أو استخدام أي سلسلة عشوائية. في هذه الحالة، يعرض Chrome واجهة مستخدم الخطأ مع رسالة خطأ عامة ويرسل الرمز إلى معالج الطلب.
  • url: تُحدِّد هذه السمة صفحة ويب قابلة للقراءة من قِبل المستخدمين تتضمّن معلومات عن الخطأ لتقديم معلومات إضافية عن الخطأ للمستخدمين. يكون هذا الحقل مفعّلاً في واجهة المستخدم المضمّنة، وهو مفيد للمستخدمين لأنّ المتصفّحات لا يمكنها تقديم رسائل خطأ مفيدة في واجهة المستخدم. على سبيل المثال: روابط للخطوات التالية أو معلومات عن كيفية التواصل مع خدمة العملاء إذا أراد المستخدم معرفة المزيد من المعلومات عن تفاصيل الخطأ وكيفية حلّه، يمكنه الانتقال إلى الصفحة المقدَّمة من واجهة مستخدم المتصفّح لمزيد من التفاصيل. يجب أن يكون عنوان URL من الموقع الإلكتروني نفسه الذي يتبع موفِّر الهوية configURL.
  // id_assertion_endpoint response
  {
    "error" : {
      "code": "access_denied",
      "url" : "https://idp.example/error?type=access_denied"
    }
  }

تصنيفات الحسابات المخصّصة

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

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

لنفترض أنّ هناك مزوّد خدمة مصادقة يريد التفريق بين حسابَي "developer" و"hr". لتحقيق ذلك، يجب أن يتيح موفِّر الهوية عنوانَي configURL لتطبيقَي "developer" و"hr" على التوالي:

  • يحتوي ملف إعداد المطوّر https://idp.example/developer/fedcm.json على تصنيف "developer"، ويحتوي ملف إعداد المؤسسة https://idp.example/hr/fedcm.json على تصنيف "hr" على النحو التالي:
  // The developer config file at `https://idp.example/developer/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "accounts": {
      // Account label
      "include": "developer"
    }
  }
  // The hr config file at `https://idp.example/hr/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "accounts": {
      // Account label
      "include": "hr"
    }
  }
  • عند إجراء هذا الإعداد، يجب أن يتضمّن ملف well-known accounts_endpoint وlogin_url للسماح بعناوين configURL متعددة:
  {
    "provider_urls": [ "https://idp.example/fedcm.json" ],
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }
  • تُعرِض نقطة نهاية حسابات موفِّر الهوية (IdP) الشائعة (في هذا المثال https://idp.example/accounts) قائمة بالحسابات التي تتضمّن موقعًا على الويب labels يتضمّن تصنيفات تمّ تعيينها في صفيف لكلّ حساب:
  {
  "accounts": [{
    "id": "123",
    "given_name": "John",
    "name": "John Doe",
    "email": "john_doe@idp.example",
    "picture": "https://idp.example/profile/123",
    "labels": ["developer"]
    }], [{
    "id": "4567",
    "given_name": "Jane",
    "name": "Jane Doe",
    "email": "jane_doe@idp.example",
    "picture": "https://idp.example/profile/4567",
    "labels": ["hr"]
    }]
  }

عندما يريد مقدّم خدمات الربط السماح لمستخدمي "hr" بتسجيل الدخول، يمكنه تحديد https://idp.example/hr/fedcm.jsonconfigURL في طلب navigator.credentials.get():

  let { token } = await navigator.credentials.get({
    identity: {
      providers: [{
        clientId: '1234',
        nonce: '234234',
        configURL: 'https://idp.example/hr/fedcm.json',
      },
    }
  });

ونتيجةً لذلك، لا يتوفّر سوى رقم تعريف الحساب 4567 للمستخدم من أجل تسجيل الدخول. يخفي المتصفّح رقم تعريف الحساب 123 بدون إشعار المستخدم كي لا يتم تزويد المستخدم بحساب غير متوافق مع موفِّر الهوية (IdP) على هذا الموقع الإلكتروني.

  • التصنيفات هي سلاسل. إذا كانت مصفوفة labels أو حقل include يحتوي على عنصر غير سلسلة، يتم تجاهله.
  • في حال عدم تحديد أي تصنيفات في configURL، سيتم عرض جميع الحسابات في أداة اختيار حسابات FedCM.
  • في حال عدم تحديد أي تصنيفات لحساب، لن يتم عرضه في أداة اختيار الحسابات إلا إذا لم تحدّد configURL أيضًا تصنيفًا.
  • إذا لم يتطابق أي حساب مع التصنيف المطلوب في الوضع التلقائي (على غرار ميزة تلميح النطاق)، يعرض مربّع حوار FedCM طلب تسجيل الدخول، ما يسمح للمستخدم بتسجيل الدخول إلى حساب موفِّر الهوية. في الوضع النشط، يتم فتح نافذة تسجيل الدخول المنبثقة مباشرةً.

إلغاء ربط نقطة النهاية

من خلال استدعاء IdentityCredential.disconnect()، يُرسِل المتصفّح طلبًا من مصدر مختلف لملف تعريف ارتباط POST يحتوي على SameSite=None ونوع محتوى هو application/x-www-form-urlencoded إلى نقطة نهاية القطع هذه مع المعلومات التالية:

الموقع الوصف
account_hint تلميح لحساب موفِّر الهوية (IdP)
client_id معرّف العميل لمسؤول المعالجة
  POST /disconnect.example HTTP/1.1
  Host: idp.example
  Origin: rp.example
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x123
  Sec-Fetch-Dest: webidentity

  account_hint=account456&client_id=rp123

عند تلقّي الطلب، يجب أن ينفّذ الخادم ما يلي:

  1. يجب الردّ على الطلب باستخدام مشاركة الموارد المتعدّدة المصادر (CORS).
  2. تأكَّد من أنّ الطلب يحتوي على عنوان Sec-Fetch-Dest: webidentity HTTP.
  3. قارِن عنوان Origin بمصدر RP الذي يحدّده العنصر client_id. رفض النموذج في حال عدم تطابقه
  4. قارِن account_hint مع أرقام تعريف الحسابات التي سبق أن سجّلت الدخول إليها.
  5. افصل حساب المستخدم عن نقطة الربط.
  6. يجب الردّ على المتصفّح بمعلومات حساب المستخدم المحدّد بتنسيق JSON.

في ما يلي مثال على حِمل JSON للاستجابة:

  {
    "account_id": "account456"
  }

بدلاً من ذلك، إذا أراد موفِّر الهوية أن يُلغي المتصفّح ربط جميع الحسابات المرتبطة بموفِّر الاعتماد، يجب تمرير سلسلة لا تتطابق مع أي رقم تعريف حساب، على سبيل المثال "*".

نقطة نهاية البيانات الوصفية للعميل

تعرض نقطة نهاية البيانات الوصفية للعميل في موفِّر الهوية البيانات الوصفية للطرف الموثوق به، مثل سياسة الخصوصية وبنود الخدمة ورموز الشعار الخاصة بالطرف الموثوق به. على مقدّمي خدمات الربط منح موفّر الهوية روابط تؤدي إلى سياسة الخصوصية وبنود الخدمة الخاصة بهم مسبقًا. يتم عرض هذين الرابطَين في مربّع حوار تسجيل الدخول عندما لا يكون المستخدم مسجَّلاً في موفِّر الموارد (RP) لدى موفِّر الهوية (IdP) بعد.

يُرسِل المتصفّح طلب GET باستخدام client_id navigator.credentials.get بدون ملفات تعريف الارتباط. على سبيل المثال:

  GET /client_metadata.example?client_id=1234 HTTP/1.1
  Host: accounts.idp.example
  Origin: https://rp.example/
  Accept: application/json
  Sec-Fetch-Dest: webidentity

عند تلقّي الطلب، يجب أن ينفّذ الخادم ما يلي:

  1. حدِّد نقطة الاتصال (RP) للعنصر client_id.
  2. يجب الردّ باستخدام البيانات الوصفية للعميل.

تشمل سمات نقطة نهاية البيانات الوصفية للعميل ما يلي:

الموقع الوصف
privacy_policy_url (اختياري) عنوان URL لسياسة خصوصية موفّر المحتوى
terms_of_service_url (اختياري) عنوان URL لبنود خدمة موفِّر المحتوى
icons (اختياري) مصفوفة من الكائنات، مثل [{ "url": "https://rp.example/rp-icon.ico", "size": 40}]

يتوقّع المتصفّح استجابة JSON من نقطة النهاية:

  {
    "privacy_policy_url": "https://rp.example/privacy_policy.html",
    "terms_of_service_url": "https://rp.example/terms_of_service.html",
    "icons": [{
          "url": "https://rp.example/rp-icon.ico",
          "size": 40
      }]
  }

يستخدم المتصفّح البيانات الوصفية للعميل المعروضة ولن تكون متاحة لوحدة التحكّم في حدود الجلسة.

عنوان URL لصفحة تسجيل الدخول

تُستخدَم نقطة النهاية هذه للسماح للمستخدم بتسجيل الدخول إلى موفِّر الهوية.

باستخدام واجهة برمجة التطبيقات Login Status API، يجب أن يُعلم موفِّر الهوية المتصفح بحالة تسجيل دخول المستخدم. ومع ذلك، قد لا تكون الحالة متزامنة، مثل عند انتهاء صلاحية الجلسة. في مثل هذا السيناريو، يمكن للمتصفّح السماح للمستخدم بتسجيل الدخول إلى موفِّر الهوية ديناميكيًا من خلال عنوان URL لصفحة تسجيل الدخول الذي تم تحديده باستخدام login_url في ملف إعدادات موفِّر الهوية.

يعرض مربّع حوار FedCM رسالة تقترح تسجيل الدخول، كما هو موضّح في الصورة التالية.

A
مربّع حوار FedCM يقترح تسجيل الدخول إلى موفِّر الهوية (IdP)

عندما ينقر المستخدم على الزر متابعة، يفتح المتصفّح نافذة منبثقة لصفحة تسجيل الدخول إلى موفِّر الهوية.

مثال على مربّع حوار FedCM
مثال على مربّع حوار يظهر بعد النقر على زر تسجيل الدخول إلى موفِّر الهوية (IdP).

مربّع الحوار هو نافذة متصفح عادية تحتوي على ملفات تعريف ارتباط الطرف الأول. إنّ أيّ مما يحدث داخل مربّع الحوار متروك لمسؤول عن إدارة الهوية، ولا تتوفّر أيّ عناصر تحكم في النوافذ لتقديم طلب تواصل بين مصادر مختلفة إلى صفحة الطرف المعتمَد. بعد تسجيل دخول المستخدم، يجب أن ينفّذ موفِّر الهوية ما يلي:

  • أرسِل رأس Set-Login: logged-in أو استخدِم واجهة برمجة التطبيقات navigator.login.setStatus("logged-in") لإعلام المتصفّح بأنّه تم تسجيل دخول المستخدِم.
  • اتصل بالرقم IdentityProvider.close() لإغلاق مربّع الحوار.
يُسجِّل المستخدِم الدخول إلى مقدّم خدمات الموافقة بعد تسجيل الدخول إلى موفِّر الهوية باستخدام FedCM.

إبلاغ المتصفّح بحالة تسجيل دخول المستخدم

Login Status API هي آلية يُعلم من خلالها الموقع الإلكتروني، ولا سيما موفّر الهوية، المتصفّح بحالة تسجيل دخول المستخدم على موفّر الهوية. باستخدام واجهة برمجة التطبيقات هذه، يمكن للمتصفّح تقليل الطلبات غير الضرورية إلى مزوّد خدمة المصادقة والحدّ من الهجمات المحتملة المتعلّقة بالتوقيت.

يمكن لموفّري الهوية إرسال حالة تسجيل دخول المستخدم إلى المتصفّح من خلال إرسال عنوان HTTP أو من خلال طلب واجهة برمجة تطبيقات JavaScript عندما يكون المستخدم مسجّلاً الدخول إلى موفّر الهوية أو عندما يكون قد سجّل الخروج من جميع حسابات موفّر الهوية. بالنسبة إلى كل موفِّر هوية (IdP) (يتم تحديده من خلال عنوان URL لملف الإعدادات)، يحتفظ المتصفّح بمتغيّر ثلاثي الحالات يمثّل حالة تسجيل الدخول بالقيم المحتمَلة التالية:

  • logged-in
  • logged-out
  • unknown (تلقائي)
حالة تسجيل الدخول الوصف
logged-in عندما يتم ضبط حالة تسجيل دخول المستخدم على logged-in، يُرسل مقدّم الطلبات الذي يتصل بـ FedCM طلبات إلى نقطة نهاية حسابات موفِّر الهوية ويعرض الحسابات المتاحة للمستخدم في مربّع حوار FedCM.
logged-out عندما تكون حالة تسجيل دخول المستخدم هي logged-out، يتعذّر الاتصال بواجهة برمجة التطبيقات FedCM بدون إرسال طلب إلى نقطة نهاية حسابات موفِّر الهوية.
unknown (تلقائي) يتم ضبط الحالة unknown قبل أن يرسل موفّر الهوية إشارة باستخدام واجهة برمجة التطبيقات Login Status API. عندما تكون الحالة unknown، يُرسل المتصفّح طلبًا إلى نقطة نهاية حسابات موفِّر الهوية ويُعدّل الحالة استنادًا إلى الاستجابة الواردة من نقطة نهاية الحسابات.

للإشارة إلى أنّ المستخدم سجّل الدخول، أرسِل رأس HTTP‏ Set-Login: logged-in في عنصر تنقّل من المستوى الأعلى أو طلب مورد فرعي من الموقع نفسه في مصدر موفِّر الهوية:

  Set-Login: logged-in

بدلاً من ذلك، يمكنك استدعاء طريقة JavaScript navigator.login.setStatus('logged-in') من مصدر موفِّر الهوية (IdP) في عملية تنقّل على مستوى أعلى:

  navigator.login.setStatus('logged-in')

سيتم ضبط حالة تسجيل دخول المستخدم على logged-in.

للإشارة إلى أنّه تم تسجيل خروج المستخدم من جميع حساباته، أرسِل عنوان HTTP‏ Set-Login: logged-out في تنقّل على مستوى أعلى أو طلب موارد فرعية على الموقع نفسه من مصدر موفِّر الهوية:

  Set-Login: logged-out

بدلاً من ذلك، يمكنك استدعاء واجهة برمجة التطبيقات JavaScript navigator.login.setStatus('logged-out') من مصدر موفِّر الهوية في مسار تنقّل من المستوى الأعلى:

  navigator.login.setStatus('logged-out')

سيتم ضبط حالة تسجيل دخول المستخدم على logged-out.

يتم ضبط الحالة unknown قبل أن يرسل موفّر الهوية إشارة باستخدام Login Status API. يُرسل المتصفّح طلبًا إلى نقطة نهاية حسابات موفِّر الهوية ويُعدِّل الحالة استنادًا إلى الاستجابة الواردة من نقطة نهاية الحسابات:

  • إذا كانت نقطة النهاية تعرض قائمة بالحسابات النشطة، عدِّل الحالة إلى logged-in وافتح مربّع حوار FedCM لعرض هذه الحسابات.
  • إذا لم تُعرِض نقطة النهاية أي حسابات، عدِّل الحالة إلى logged-out و أوقِف طلب FedCM.

السماح للمستخدم بتسجيل الدخول من خلال عملية تسجيل دخول ديناميكية

على الرغم من أنّ موفّر الهوية (IdP) يواصل إبلاغ المتصفّح بحالة تسجيل دخول المستخدم، قد لا تكون البيانات متزامنة، مثلما يحدث عند انتهاء صلاحية الجلسة. يحاول المتصفّح إرسال طلب مزوّد ببيانات اعتماد إلى نقطة نهاية الحسابات عندما تكون حالة تسجيل الدخول هي logged-in، ولكن لا يعرض الخادم أي حسابات لأنّ الجلسة لم تعد متوفّرة. في مثل هذا السيناريو، يمكن للمتصفّح السماح للمستخدم بشكل ديناميكي بتسجيل الدخول إلى موفِّر الهوية من خلال نافذة منبثقة.

Next steps

Implement FedCM for your RPs and distribute the JavaScript SDK. Keep RPs up-to-date by eliminating the need for self-implementation.
Learn how to setup your enviromnemt and debug your implementation.