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

يتضمّن تنفيذ FedCM عدة خطوات أساسية لكل من موفِّر الهوية والطرف المعتمِد. راجِع المستندات للتعرّف على كيفية تنفيذ FedCM على جانب موفّر الهوية.

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

إنشاء ملف 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/، يجب أن تعرض ملف well-known على 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. سيمرّر "موفّر الخدمة" عنوان URL لملف الإعداد لكل موفّر هوية:

  // Executed on RP's side:
  try {
    const credential = await navigator.credentials.get({
      identity: {
        providers: [
          {
            // To allow users to sign in with the IdP1 using FedCM, RP specifies the IdP's config file URL:
            configUrl: 'https://idp1.example/foo.json', // first IdP
            clientId: '123',
          },
          // To allow users to sign in with the IdP2 using FedCM, RP specifies the IdP's config file URL.
          // Note that multiple IdPs in a single get() are supported from Chrome 136.
          {
            configUrl: 'https://idp2.example/bar.json', // second IdP
            clientId: '456',
          },
        ],
      },
    });

    const token = credential.token;
    // Get the current IdP's configURL to identify which provider the user is signed in with
    const currentIdpConfigUrl = credential.configURL;
    if (currentIdpConfigUrl === 'https://idp1.example/foo.json') {
      // handle the case where the user signed in with idp1
    } else if (currentIdpConfigUrl === 'https://idp2.example/bar.json') {
      // handle the case where the user signed in with idp2
    }
  } catch (error) {
    // handle error
  }

سيجلب المتصفّح ملف الإعدادات باستخدام طلب 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 لنقطة نهاية الحسابات
account_label (اختياري) سلسلة تصنيف الحساب المخصّص، التي تحدّد الحسابات التي يجب عرضها عند استخدام ملف الإعداد هذا، مثل: "account_label": "developer".
يمكن لموفّر الهوية تنفيذ تصنيف الحسابات المخصّص على النحو التالي:

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

ملاحظة: تتوفّر تصنيفات الحسابات المخصّصة بدءًا من الإصدار 132 من Chrome.
supports_use_other_account (اختياري) قيمة منطقية تحدّد ما إذا كان بإمكان المستخدم تسجيل الدخول باستخدام حساب مختلف عن الحساب الذي سجّل الدخول إليه حاليًا (إذا كان موفّر خدمة تحديد الهوية يتيح استخدام حسابات متعددة). ينطبق ذلك على وضع النشاط فقط.
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 بكسل في الوضع النشط.

في ما يلي مثال على نص الرد من موفّر خدمة تحديد الهوية:

  {
    "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.
    "account_label": "developer",
    "supports_use_other_account": true,
    "branding": {
      "background_color": "green",
      "color": "#FFEEAA",
      "icons": [{
        "url": "https://idp.example/icon.ico",
        "size": 25
      }]
    }
  }

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

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

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

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

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

  {
    "accounts_endpoint" : "/accounts.example",
    "supports_use_other_account": true
  }

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

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

يرسل المتصفّح طلب 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 الاسم الكامل للمستخدم وفقًا للغته وإعداداته المفضّلة

ملاحظة: بدءًا من الإصدار 141 من Chrome، يجب توفير إحدى المَعلمات name أو email أو username أو tel على الأقل. في إصدارات Chrome السابقة، يجب توفُّر كلّ من name وemail.
username اسم مستخدم يختاره المستخدم

ملاحظة: بدءًا من الإصدار 141 من Chrome، يجب توفير إحدى المَعلمات name أو email أو username أو tel على الأقل.
email عنوان البريد الإلكتروني للمستخدم.

ملاحظة: بدءًا من الإصدار 141 من Chrome، يجب توفير إحدى المَعلمات name أو email أو username أو tel على الأقل. في إصدارات Chrome السابقة، يجب توفُّر كلّ من name وemail.
tel رقم هاتف المستخدِم

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

على سبيل المثال، ينفّذ موفِّر الهوية https://idp.example/developer-config.json ملف إعداد مع تحديد "account_label": "developer". تضع خدمة IdP أيضًا التصنيف "developer" على بعض الحسابات باستخدام المَعلمة label_hints في نقطة نهاية الحسابات. عندما يطلب RP 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.
      "label_hints": ["enterprise", "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']. ويجب توفُّرها للتوافق مع الأنظمة القديمة التي تستخدم عمليات التنفيذ القديمة.

    ملاحظة: اعتبارًا من الإصدار 141 من Chrome، قد يتم عرض نص الإفصاح حتى إذا كانت قيمة disclosure_text_shown هي "false". للتحقّق مما إذا كان نص الإفصاح قد تم عرضه، راجِع قيمة disclosure_shown_for بدلاً من ذلك.
disclosure_shown_for تدرِج هذه السمة الحقول التي عرضها المتصفّح للمستخدم في نص الإفصاح لإعلامه بالبيانات التي يطلبها الطرف المعتمد من موفِّر الهوية.
is_auto_selected في حال إجراء إعادة المصادقة تلقائيًا على RP، يشير is_auto_selected إلى "true". في الحالات الأخرى، قُل "false". ويساعد ذلك في توفير المزيد من الميزات المتعلّقة بالأمان. على سبيل المثال، قد يفضّل بعض المستخدمين مستوى أمان أعلى يتطلّب وسيطة صريحة من المستخدم في عملية المصادقة. إذا تلقّى موفّر خدمة تحديد الهوية طلب رمز مميّز بدون هذا التوسّط، يمكنه التعامل مع الطلب بشكل مختلف. على سبيل المثال، يمكنك عرض رمز خطأ يتيح لموفّر الهوية استدعاء FedCM API مرة أخرى باستخدام mediation: required.
fields (اختياري) مصفوفة من السلاسل تحدّد معلومات المستخدم التي طلب من موفّر خدمة الهوية مشاركتها. يمكن تحديد الحقول التالية بشكل اختياري:
  • "name"
  • "username"
  • "email"
  • "tel"
  • "picture"
سيرسل المتصفّح fields وdisclosure_text_shown وdisclosure_shown_for مع تضمين الحقول المحدّدة في طلب POST، كما هو موضّح في المثال التالي.

ملاحظة: تتوافق Fields API مع الإصدار 132 من Chrome والإصدارات الأحدث. يتوفّر الحقلان `"username"` و `"tel"` بدءًا من الإصدار 141 من 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&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 مع أوضاع التوسّط المختلفة:

  • في وضع passive:
    • 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",
    "account_label": "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",
    "account_label": "hr"
  }
  • في حال استخدام هذا الإعداد، يجب أن يتضمّن ملف well-known القيمتَين accounts_endpoint وlogin_url للسماح باستخدام عناوين URL متعددة خاصة بالإعدادات:
  {
    "provider_urls": [ "https://idp.example/fedcm.json" ],
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }
  • تعرض نقطة نهاية الحسابات الشائعة لموفّر خدمة تحديد الهوية (IdP) (في هذا المثال https://idp.example/accounts) قائمة بالحسابات تتضمّن السمة label_hints مع التصنيفات المعيّنة في مصفوفة لكل حساب:
  {
  "accounts": [{
    "id": "123",
    "given_name": "John",
    "name": "John Doe",
    "email": "john_doe@idp.example",
    "picture": "https://idp.example/profile/123",
    "label_hints": ["developer"]
    }], [{
    "id": "4567",
    "given_name": "Jane",
    "name": "Jane Doe",
    "email": "jane_doe@idp.example",
    "picture": "https://idp.example/profile/4567",
    "label_hints": ["hr"]
    }]
  }

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

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

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

اعتبارات إضافية:

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

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

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

الموقع الوصف
account_hint تلميح لحساب موفّر الهوية
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، على موفّر الهوية إبلاغ المتصفّح بحالة تسجيل الدخول الخاصة بالمستخدم. ومع ذلك، قد لا تكون الحالة متزامنة، مثلاً عندما تنتهي صلاحية الجلسة. في مثل هذه الحالة، يمكن للمتصفّح أن يتيح للمستخدم تسجيل الدخول إلى موفِّر الهوية (IdP) بشكل ديناميكي من خلال عنوان URL لصفحة تسجيل الدخول المحدّد باستخدام ملف إعداد موفِّر الهوية login_url.

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

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

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

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

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

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

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

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

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

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

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

  Set-Login: logged-in

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

  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. يرسل المتصفّح طلبًا إلى نقطة نهاية الحسابات الخاصة بموفّر خدمة تحديد الهوية ويعدّل الحالة استنادًا إلى الردّ الوارد من نقطة نهاية الحسابات:

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

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

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

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

نفِّذ FedCM لموفّري المحتوى ووزِّع حزمة تطوير البرامج (SDK) لـ JavaScript. إبقاء خطط التسويق متوفّرة من خلال إزالة الحاجة إلى التنفيذ الذاتي
تعرَّف على كيفية إعداد البيئة وتصحيح أخطاء التنفيذ.