بدءًا من الإصدار 126 من Chrome، يمكن للمطوّرين بدء تشغيل إصدار تجريبي من حِزمة ميزات واجهة برمجة التطبيقات Federated Credential Management API (FedCM) لأجهزة الكمبيوتر المكتبي التي تتيح بعض حالات استخدام التفويض. تتألف الحزمة من Continuation API و Parameters API، اللتين تتيحان تجربة مشابهة لمسار التفويض في OAuth تتضمن مربّع حوار الإذن المقدَّم من موفِّر الهوية (IdP). تتضمّن الحزمة أيضًا تغييرات أخرى، مثل Fields API وMultiple configURLs وCustom Account Labels. اعتبارًا من الإصدار 126 من Chrome، سنقدّم أيضًا فترة تجريبية لمصدر واجهة برمجة التطبيقات Storage Access API (SAA) التي تمنح طلبات SAA تلقائيًا إذا سجّل المستخدم بنجاح الدخول باستخدام FedCM في السابق.
مرحلة التجربة والتقييم: حِزمة FedCM Continuation API
تتألف حزمة FedCM Continuation API من عدة إضافات FedCM:
Continuation API
يمكنك الاطّلاع على عرض توضيحي لواجهة برمجة التطبيقات على Glitch.
تسمح Continuation API لنقطة نهاية تأكيد الهوية في موفِّر الهوية بالاستجابة لعنوان URL اختياريًا يعرضه FedCM للسماح للمستخدم بمواصلة مسار تسجيل الدخول المتعدّد الخطوات. يسمح ذلك لموفِّر الهوية بطلب منح المستخدم أذونات للطرف الموثوق به (RP) تتجاوز ما هو ممكن في واجهة مستخدم FedCM الحالية، مثل الوصول إلى موارد المستخدم من جهة الخادم.
عادةً ما تعرض نقطة نهاية بيان الهوية رمزًا مميزًا مطلوبًا لتأكيد هوية العميل.
{
"token": "***********"
}
ومع ذلك، باستخدام Continuation API، يمكن أن تُعرِض نقطة نهاية continue_on
continue_on
التي تتضمّن مسارًا مطلقًا أو continue_on
نسبيًا إلى نقطة نهاية 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 pop-up window:
"continue_on": "/oauth/authorize?scope=..."
}
بعد أن يتلقّى المتصفّح استجابة continue_on
، يتم فتح نافذة منبثقة جديدة وينتقل المستخدم إلى المسار المحدّد.
بعد تفاعل المستخدم مع الصفحة، على سبيل المثال منح إذن إضافي
لمشاركة معلومات إضافية مع مقدّم الخدمة، يمكن لصفحة موفِّر الهوية الاتصال
IdentityProvider.resolve()
لحلّ طلب
navigator.credentials.get()
الأصلي وعرض رمز مميّز كوسيطة.
document.getElementById('allow_btn').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.close()
.
IdentityProvider.close();
إذا غيّر المستخدم حسابه في النافذة المنبثقة لأي سبب (على سبيل المثال، يقدّم موفِّر الهوية والخدمات (IdP) وظيفة "تبديل المستخدم"، أو في حالات التفويض)، يأخذ الإجراء resolve مَعلمة ثانية اختيارية تسمح بإجراء ما يلي:
IdentityProvider.resolve(token, {accountId: '1234');
Parameters API
تسمح Parameters API لـ RP بتقديم مَعلمات إضافية إلى نقطة نهاية ملف تعريف هوية العميل. باستخدام Parameters API، يمكن لموفّري خدمات الربط تمرير مَعلمات إضافية إلى موفّر الهوية لطلب أذونات للموارد التي تتجاوز عملية تسجيل الدخول الأساسية. سيفوّض المستخدم هذه الأذونات من خلال مسار تجربة مستخدم يتحكّم فيه موفِّر الهوية ويتم تشغيله من خلال واجهة برمجة التطبيقات Continuation API.
لاستخدام واجهة برمجة التطبيقات، أضِف مَعلمات إلى السمة params
كعنصر في طلب navigator.credentials.get()
.
let {token} = await navigator.credentials.get({
identity: {
providers: [{
clientId: '1234',
configURL: 'https://idp.example/fedcm.json',
// Key/value pairs that need to be passed from the
// RP to the IdP but that don't really play any role with
// the browser.
params: {
IDP_SPECIFIC_PARAM: '1',
foo: 'BAR',
ETC: 'MOAR',
scope: 'calendar.readonly photos.write',
}
},
}
});
يتمّ وضع param_
في بداية أسماء السمات في عنصر params
. في المثال
أعلاه، تحتوي سمة params على IDP_SPECIFIC_PARAM
ك'1'
وfoo
ك'BAR'
وETC
ك'MOAR'
وscope
ك'calendar.readonly photos.write'
.
سيتم تحويل هذا العنوان إلى
param_IDP_SPECIFIC_PARAM=1¶m_foo=BAR¶m_ETC=MOAR¶m_scope=calendar.readonly%20photos.write
في نص طلب HTTP:
POST /fedcm_assertion_endpoint HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=false¶m_IDP_SPECIFIC_PARAM=1¶m_foo=BAR¶m_ETC=MOAR¶m_scope=calendar.readonly%20photos.write
الحصول على الأذونات ديناميكيًا
بشكل عام، من المفيد للمستخدمين طلب الأذونات عند الحاجة إليها، بدلاً من طلبها عندما يرى المطوّر أنّه من الأسهل تنفيذها. على سبيل المثال، يُفضّل طلب الإذن بالوصول إلى الكاميرا عندما يكون المستخدم على وشك التقاط صورة بدلاً من طلب الإذن فور وصوله إلى الموقع الإلكتروني. وينطبق الإجراء نفسه على موارد الخادم. اطلب الأذونات فقط عند الحاجة إليها للمستخدم. ويُعرف ذلك باسم "التفويض الديناميكي".
لطلب التفويض ديناميكيًا باستخدام FedCM، يمكن لموفِّر الهوية (IdP) إجراء ما يلي:
- اتصل بـ
navigator.credentials.get()
باستخدام المَعلمات المطلوبة التي يمكن لموفِّر الهوية فهمها، مثلscope
. - تؤكد نقطة نهاية تأكيد الهوية
أنّ المستخدم قد سجّل الدخول من قبل وتستجيب بعنوان URL
continue_on
. - يفتح المتصفّح نافذة منبثقة تتضمّن صفحة أذونات موفِّر الهوية (IdP) التي تطلب إذنًا إضافيًا يتطابق مع النطاقات المطلوبة.
- بعد أن يحصل موفِّر الهوية على إذن عبر
IdentityProvider.resolve()
، يتم إغلاق النافذة ويحصل طلبnavigator.credentials.get()
الأصلي من مقدّم طلب الاعتماد على رمز مميّز ذي صلة أو رمز تفويض حتى يتمكّن مقدّم طلب الاعتماد من تبديله برمز مميّز مناسب للوصول.
Fields API
تسمح Fields API لموفّر المحتوى بالتعرّف على سمات الحساب المطلوب الحصول عليها من موفّر الهوية حتى يتمكّن المتصفّح من عرض واجهة مستخدم مناسبة للإفصاح في مربّع حوار FedCM، وتقع على عاتق موفّر الهوية مسؤولية تضمين الحقول المطلوبة في الرمز المرجعي الذي يتم إرجاعه. يمكنك اعتبار هذا الطلب هو طلب "ملف شخصي أساسي" في OpenID Connect مقارنةً بـ "النطاقات" في OAuth.


لاستخدام Fields API، أضِف مَعلمات إلى السمة fields
كصفيف في طلب navigator.credentials.get()
. يمكن أن تحتوي الحقول على 'name'
و'email'
و'picture'
في الوقت الحالي، ولكن يمكن توسيعها لتشمل المزيد من القيم في
المستقبل.
سيظهر الطلب الذي يتضمّن fields
على النحو التالي:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
fields: ['name', 'email', 'picture'],
clientId: '1234',
configURL: 'https://idp.example/fedcm.json',
params: {
scope: 'drive.readonly calendar.readonly',
}
},
}
mediation: 'optional',
});
يتضمّن طلب HTTP المُرسَل إلى نقطة نهاية بيان الهوية
المَعلمة fields
التي يحدّدها مقدّم الخدمة، مع ضبط المَعلمة disclosure_text_shown
على القيمة true
إذا لم يكن هذا مستخدمًا متكرّرًا، والحقول التي كشف عنها
المتصفّح للمستخدم في المَعلمة disclosure_shown_for
:
POST /id_assertion_endpoint HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=true&fields=email,name,picture&disclosure_shown_for=email,name,picture
إذا كان مقدّم الخدمة يحتاج إلى الوصول إلى أي بيانات إضافية من موفِّر الهوية، مثل الوصول إلى جدول تضامني، يجب معالجة ذلك باستخدام مَعلمة مخصّصة كما هو موضّح أعلاه. يعرض
موفِّر الهوية عنوان URL continue_on
لطلب الإذن.
إذا كان fields
صفيفًا فارغًا، سيظهر الطلب على النحو التالي:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
fields: [],
clientId: '1234',
configURL: 'https://idp.example/fedcm.json',
params: {
scope: 'drive.readonly calendar.readonly',
}
},
}
mediation: 'optional',
});
إذا كان fields
صفيفًا فارغًا، سيتخطّى وكيل المستخدم واجهة مستخدم بيان الإفصاح.

وينطبق ذلك حتى إذا كان الردّ من نقطة نهاية
الحسابات
لا يحتوي على رقم تعريف عميل يتطابق مع مقدّم خدمات الاعتماد في approved_clients
.
في هذه الحالة، يكون العنصر disclosure_text_shown
الذي تم إرساله إلى نقطة نهاية disclosure_text_shown
هو
خطأ في نص HTTP:
POST /id_assertion_endpoint HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=false
عناوين URL متعددة لإعدادات التطبيق
تسمح عناوين URL المتعدّدة لملف الإعداد لموفّري الهوية
باستخدام ملفات إعدادات متعددة لموفّر الهوية، وذلك من خلال تحديد
accounts_endpoint
وlogin_url
في ملف well-known بالطريقة نفسها
المُستخدَمة في ملفات الإعداد.
في حال إضافة accounts_endpoint
وlogin_url
إلى ملف well-known، يتم تجاهل
provider_urls
لكي يتمكّن موفِّر الهوية من إتاحة ملفات إعدادات متعددة.
وإذا لم تكن كذلك، سيستمر تطبيق provider_urls
حتى يكون متوافقًا مع الإصدارات القديمة.
يمكن أن يبدو ملف well-known الذي يتيح عناوين configURL متعددة على النحو التالي:
{
"provider_urls": [ "https://idp.example/fedcm.json" ],
"accounts_endpoint": "https://idp.example/accounts",
"login_url": "https://idp.example/login"
}
يتيح لنا ذلك ما يلي:
- الحفاظ على التوافق مع الإصدارات السابقة واللاحقة من الملفات المعروفة والإصدارات السابقة من المتصفّحات التي تم نشرها من قبل
- أن تتضمّن عددًا عشوائيًا من ملفات الإعداد، ما دامت جميعها تشير إلى
accounts_endpoint
وlogin_url
نفسهما - لا تتوفّر فرصة لإضافة معلومات الالتباس إلى طلب الجلب المزوّد ببيانات الاعتماد الذي يتم توجيهه إلى
accounts_endpoint
، لأنّه يجب تحديدها على مستوى ".well-known".
إنّ إتاحة عناوين configURLs متعددة اختيارية، ويمكن أن تظل عمليات تنفيذ FedCM الحالية كما هي.
تصنيفات الحسابات المخصّصة
تسمح تصنيفات الحساب المخصّصة لموفّري idenityFedCM
IdP بإضافة تعليقات توضيحية إلى الحسابات حتى يتمكّن موفّري خدمات الربط من فلترتها من خلال تحديد التصنيف فيملف الإعدادات. كان من الممكن إجراء فلترة مشابهة باستخدام واجهة برمجة تطبيقات "ملاحظة النطاق" وواجهة برمجة تطبيقات "ملاحظة تسجيل الدخول" من خلال تحديد
هذه الملاحظات في طلب navigator.credentials.get()
، ولكن يمكن أن تصفِّل تصنيفات الحسابات المخصّصة
المستخدمين من خلال تحديد ملف الإعدادات، وهو أمر مفيد بشكل خاص عند استخدام
عناوين URL متعددة لملف الإعدادات. تختلف أيضًا تصنيفات الحسابات المخصّصة
في أنّها يتم توفيرها من خادم موفّر الهوية، بدلاً من
موفّر الاعتماد، مثل إشارات تسجيل الدخول أو النطاق.
مثال
يتوافق موفِّر الهوية مع عنصرَي configURL للمستهلك والمؤسسة على التوالي. يحتوي
ملف إعدادات المستهلك على تصنيف 'consumer'
، ويحتويملف إعدادات المؤسسة
على تصنيف 'enterprise'
.
باستخدام هذا الإعداد، يتضمّن ملف 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"
}
عند تقديم accounts_endpoint
في ملف well-known، يتم تجاهل
provider_urls
. يمكن أن يشير RP مباشرةً إلى ملفات الإعدادات
المعنية في طلب navigator.credentials.get()
.
يمكن العثور على ملف إعدادات المستهلك على https://idp.example/fedcm.json
الذي يتضمّن سمة
accounts
التي تحدّد 'consumer'
باستخدام include
.
{
"accounts_endpoint": "https://idp.example/accounts",
"client_metadata_endpoint": "/client_metadata",
"login_url": "https://idp.example/login",
"id_assertion_endpoint": "/assertion",
"accounts": {
"include": "consumer"
}
}
يمكن العثور على ملف إعدادات المؤسسة على العنوان https://idp.example/enterprise/fedcm.json
، ويحتوي على السمة accounts
التي تحدّد 'enterprise'
باستخدام
include
.
{
"accounts_endpoint": "https://idp.example/accounts",
"client_metadata_endpoint": "/enterprise/client_metadata",
"login_url": "https://idp.example/login",
"id_assertion_endpoint": "/assertion",
"accounts": {
"include": "enterprise"
}
}
تُعرِض نقطة نهاية
حسابات العميل المشترَك لمزوّد الهوية (في هذا المثال 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": ["consumer"]
}], [{
"id": "4567",
"given_name": "Jane",
"name": "Jane Doe",
"email": "jane_doe@idp.example",
"picture": "https://idp.example/profile/4567",
"labels": ["enterprise"]
}]
}
عندما يريد مقدّم خدمات الربط السماح لمستخدمي 'enterprise'
بتسجيل الدخول، يمكنه تحديد
'enterprise'
configURL 'https://idp.example/enterprise/fedcm.json'
في
navigator.credentials.get()
الطلب:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
clientId: '1234',
nonce: '234234',
configURL: 'https://idp.example/enterprise/fedcm.json',
},
}
});
نتيجةً لذلك، لا يتوفّر سوى رقم تعريف الحساب '4567'
للمستخدم من أجل تسجيل
الدخول. يخفي المتصفّح رقم تعريف الحساب '123'
بدون إشعار المستخدم كي لا يتم تزويده بحساب غير متوافق مع موفّر الهوية (IdP) على هذا الموقع الإلكتروني.
مرحلة التجربة والتقييم: FedCM كإشارة ثقة لواجهة برمجة التطبيقات Storage Access API
سيبدأ الإصدار 126 من Chrome مرحلة التجربة والتقييم لإدخال واجهة برمجة التطبيقات FedCM كإشارة ثقة لواجهة برمجة التطبيقات Storage Access. وبفضل هذا التغيير، تصبح منح الأذونات مسبقًا من خلال FedCM سببًا صالحًا لموافقة واجهات برمجة التطبيقات لوصول التخزين تلقائيًا على طلب الوصول إلى مساحة التخزين.
يكون ذلك مفيدًا عندما يريد إطار iframe مضمّن الوصول إلى موارد مخصّصة: على سبيل المثال، إذا كان idp.example مضمّنًا في rp.example ويحتاج إلى عرض مورد مخصّص. إذا فرض المتصفّح قيودًا على الوصول إلى ملفات تعريف الارتباط التابعة لجهات خارجية، حتى إذا كان المستخدم مسجِّلاً الدخول إلى rp.example باستخدام idp.example مع FedCM، لن يتمكّن إطار iframe المضمّن من idp.example من طلب موارد مخصّصة لأنّ الطلبات لن تتضمّن ملفات تعريف الارتباط التابعة لجهات خارجية.
لتحقيق ذلك، يجب أن يحصل idp.example على إذن الوصول إلى مساحة التخزين من خلال ملف div مضمّن في الموقع الإلكتروني، ولا يمكن الحصول على هذا الإذن إلا من خلال طلب div.
باستخدام FedCM كإشارة ثقة لواجهة برمجة التطبيقات Storage Access API، لا تقبل عمليات التحقّق من أذونات واجهة برمجة التطبيقات Storage Access API منح الإذن الذي يتم منحه من خلال طلب الوصول إلى مساحة التخزين، بل تقبل أيضًا منح الإذن الذي يتم منحه من خلال طلب FedCM.
// In top-level rp.example:
// Ensure FedCM permission has been granted.
const cred = await navigator.credentials.get({
identity: {
providers: [{
configURL: 'https://idp.example/fedcm.json',
clientId: '123',
}],
},
mediation: 'optional',
});
// In an embedded IdP iframe:
// No user gesture is needed to call this, and the call will be auto-granted.
await document.requestStorageAccess();
// This returns `true`.
const hasAccess = await document.hasStorageAccess();
بعد تسجيل دخول المستخدم باستخدام FedCM، يتم منح الإذن تلقائيًا طالما أنّ مصادقة FedCM نشطة. وهذا يعني أنّه بعد انقطاع اتصال المستخدم، سيظهر طلب الإذن.
المشاركة في الفترة التجريبية لإصدار التطبيق الأصلي
يمكنك تجربة حِزمة FedCM Continuation API محليًا من خلال تفعيل علامة Chrome
chrome://flags#fedcm-authz
على الإصدار 126 من Chrome أو الإصدارات الأحدث. يمكنك أيضًا تجربة FedCM
كإشارة ثقة لواجهة برمجة التطبيقات Storage Access API على الجهاز من خلال تفعيل
#fedcm-with-storage-access-api
على Chrome 126 أو الإصدارات الأحدث.
تتوفّر هذه الميزات أيضًا كإصدارات تجريبية في المصدر. تتيح لك مراحل التجربة والتقييم تجربة ميزات جديدة وتقديم ملاحظات حول سهولة استخدامها وفعاليتها ومدى ملاءمتها للتطبيق. لمزيد من المعلومات، اطّلِع على مقالة البدء في استخدام تجارب المصدر.
لتجربة حزمة FedCM Continuation API لميزة "متابعة المحادثة"، أنشئ رمزَي مميّزَين لميزة "متابعة المحادثة":
- سجِّل في الفترة التجريبية. أدرِج الرمز المميّز في مصدر موفِّر الهوية (IdP).
- سجِّل في الفترة التجريبية الأصلية مع وضع علامة في مربّع الاختيار "مطابقة الجهات الخارجية". اتّبِع التعليمات الواردة في مقالة تسجيل تجربة مصدر تابعة لجهة خارجية للخدمة لتضمين الرمز المميّز للخدمة.
إذا كنت مهتمًا بتفعيل Continuation API مع مسار الزر، فعِّل إصدار Button Mode API التجريبي أيضًا:
- سجِّل في الفترة التجريبية الأصلية بصفتك جهة خارجية. اتّبِع التعليمات الواردة في مقالة تسجيل تجربة مصدر تابعة لجهة خارجية لبرنامج الإصدار التجريبي لتضمين الرمز المميّز لبرنامج الإصدار التجريبي.
لتجربة FedCM كإشارة ثقة لمصدر Storage Access API:
- سجِّل في الفترة التجريبية الأصلية. أدرِج الرمز المميّز في مصدر موفِّر الهوية (IdP).
تتوفّر مرحلة التجربة والتقييم لحزمة Continuation API وFedCM كإشارة ثقة لمرحلة التجربة والتقييم لواجهة برمجة التطبيقات Storage Access API اعتبارًا من الإصدار 126 من Chrome.
تسجيل فترة تجريبية لجهة خارجية في "المسؤول عن المعالجة"
- انتقِل إلى صفحة تسجيل الفترة التجريبية الأصلية.
- انقر على الزر تسجيل واملأ النموذج لطلب رمز مميّز.
- أدخِل مصدر موفِّر خدمة المصادقة على أنّه مصدر الويب.
- تحقَّق من مطابقة الجهات الخارجية لإدراج الرمز المميّز باستخدام JavaScript في مصادر أخرى.
- انقر على إرسال.
- تضمين الرمز المميّز الصادر على موقع إلكتروني تابع لجهة خارجية
لتضمين الرمز المميّز على موقع إلكتروني تابع لجهة خارجية، أضِف الرمز التالي إلى مكتبة JavaScript أو حِزمة تطوير البرامج (SDK) لمزوّد خدمة تعريف الهوية التي يتم عرضها من مصدر مزوّد خدمة تعريف الهوية.
const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);
استبدِل TOKEN_GOES_HERE
برمزك المميّز.