بدءًا من Chrome 126، يمكن للمطوِّرين بدء تشغيل نسخة تجريبية من حزمة من ميزات 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
- واجهة برمجة التطبيقات للمعلَمات
- Fields API
- عدة configURLs
- تصنيفات الحسابات المخصّصة
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، يمكن لموفّري خدمات الربط تمرير مَعلمات إضافية إلى موفّر الهوية لطلب أذونات للموارد التي تتجاوز عملية تسجيل الدخول الأساسية. يجب أن يسمح المستخدم بهذه الأذونات من خلال تدفق تجربة مستخدم يتحكم فيه موفِّر الهوية (idP) ويتم تشغيله عبر واجهة برمجة تطبيقات 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 لموفّر المحتوى بالإعلان عن سمات الحساب المطلوب الحصول عليها من موفّر الهوية حتى يتمكّن المتصفّح من عرض واجهة مستخدم مناسبة للإفصاح في مربّع حوار 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
إذا كان الجهة المحظورة بحاجة إلى الوصول إلى أي بيانات إضافية من موفِّر الهوية، مثل الوصول إلى أحد التقاويم، يجب التعامل مع ذلك باستخدام مَعلمة مخصَّصة كما هو مذكور أعلاه. يعرض موفِّر الهوية (IdP) عنوان URL لطلب الإذن.
إذا كان 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
صفيفًا فارغًا، سيتخطّى وكيل المستخدم واجهة مستخدم بيان الإفصاح.
وينطبق ذلك حتى إذا كان الردّ من نقطة نهاية
accounts
لا يحتوي على رقم تعريف عميل يتطابق مع مقدّم الخدمة في approved_clients
.
في هذه الحالة، يكون العنصر 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
عناوين configURL المتعددة
تتيح عناوين URL المتعددة لموفّري الهوية إمكانية إضافة عدة ملفات إعداد لموفِّر الهوية من خلال تحديد accounts_endpoint
وlogin_url
في الملف المعروف بالطريقة نفسها المُتّبعة في ملفات الضبط.
في حال إضافة accounts_endpoint
وlogin_url
إلى الملف المعروف، يتم تجاهل 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".
يُرجى العلم أنّ إتاحة عدة عناوين URL للإعداد هي إجراء اختياري، ويمكن أن تظلّ عمليات تنفيذ "المراسلة عبر السحابة الإلكترونية من Firebase" الحالية كما هي.
تصنيفات الحسابات المخصّصة
تسمح تصنيفات الحساب المخصّصة لموفّري idenityFedCM
IdP بإضافة تعليقات توضيحية إلى الحسابات حتى يتمكّن موفّري خدمات الربط من فلترتها من خلال تحديد التصنيف فيملف الإعدادات. توفّرت إمكانية إجراء فلترة مشابهة باستخدام واجهة برمجة تطبيقات اقتراح النطاق وواجهة برمجة تطبيقات تلميح تسجيل الدخول من خلال تحديدهما في طلب navigator.credentials.get()
، إلا أنّ "تصنيفات الحساب المخصّص" يمكنها فلترة المستخدمين من خلال تحديد ملف الإعداد، وهو أمر مفيد بشكل خاص عند استخدام عناوين configURL متعددة. وتختلف أيضًا تصنيفات الحسابات المخصّصة من حيث أنّها يتم توفيرها من خادم موفِّر الهوية (idP)، وليس من الجهة المحظورة، مثل تلميحات تسجيل الدخول أو النطاق.
مثال
يتوافق موفِّر الهوية مع عنوانَي 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
في الملف المعروف، يتم تجاهل 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، لا تقبل عمليات التحقق من أذونات واجهة برمجة التطبيقات 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 نشطة. هذا يعني أنه بمجرد إلغاء اتصال المستخدم، سيؤدي طلب الإذن إلى ظهور رسالة مطالبة.
المشاركة في مرحلة التجربة والتقييم
يمكنك تجربة حزمة واجهة برمجة التطبيقات Continuation API في FedCM محليًا من خلال تفعيل علامة Chrome
chrome://flags#fedcm-authz
في الإصدار 126 من Chrome أو إصدار أحدث. يمكنك أيضًا تجربة FedCM
كإشارة ثقة لواجهة برمجة التطبيقات Storage Access API على الجهاز من خلال تفعيل
#fedcm-with-storage-access-api
على Chrome 126 أو الإصدارات الأحدث.
تتوفّر هذه الميزات أيضًا كإصدارات تجريبية في المصدر. تتيح لك مراحل التجربة والتقييم تجربة ميزات جديدة وتقديم ملاحظات حول سهولة استخدامها وفعاليتها ومدى ملاءمتها للتطبيق. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة بدء استخدام مراحل التجربة والتقييم.
لتجربة حزمة FedCM Continuation API لميزة "متابعة المحادثة" ، أنشئ رمزَي مميّزَين لتجربة ميزة "متابعة المحادثة":
- يُرجى التسجيل في الفترة التجريبية. أدرِج الرمز المميّز في مصدر موفِّر الهوية (IdP) .
- سجِّل في الفترة التجريبية الأصلية مع وضع علامة في مربّع الاختيار "مطابقة الجهات الخارجية". اتّبِع التعليمات الواردة في مقالة تسجيل تجربة مصدر تابعة لجهة خارجية للخدمة لتضمين الرمز المميّز للخدمة.
إذا كنت مهتمًا بتفعيل واجهة برمجة التطبيقات Continuation API مع تدفق الزر، يمكنك تفعيل التجربة الأصلية لواجهة برمجة التطبيقات لوضع الزر أيضًا:
- سجِّل في الفترة التجريبية الأصلية بصفتك جهة خارجية. اتّبِع التعليمات الواردة في مقالة تسجيل فترة تجريبية للمصدر تابع لجهة خارجية في الجهة المحظورة بهدف تضمين الرمز المميّز الخاص بالجهة المحظورة.
لتجربة إطار عمل FedCM كإشارة ثقة في مرحلة التجربة والتقييم على واجهة برمجة التطبيقات Storage Access، اتّبِع الخطوات التالية:
- سجِّل في الفترة التجريبية الأصلية. أدرِج الرمز المميّز في مصدر موفِّر الهوية (IdP) .
من الإصدار Chrome 126، تتوفّر مرحلة التجربة والتقييم في حزمة Continuation API وFedCM كإشارة ثقة في مرحلة التجربة والتقييم في Storage Access API.
تسجيل فترة تجريبية لجهة خارجية في "المسؤول عن المعالجة"
- انتقِل إلى صفحة التسجيل في مرحلة التجربة والتقييم.
- انقر على الزر تسجيل واملأ النموذج لطلب رمز مميّز.
- أدخِل مصدر موفِّر خدمة المصادقة على أنّه مصدر الويب.
- تحقَّق من مطابقة الجهات الخارجية لإدراج الرمز المميّز باستخدام JavaScript في مصادر أخرى.
- انقر على إرسال.
- تضمين الرمز المميّز الصادر على موقع إلكتروني تابع لجهة خارجية
لتضمين الرمز المميّز على موقع إلكتروني تابع لجهة خارجية، أضِف الرمز التالي إلى مكتبة JavaScript أو حزمة تطوير البرامج (SDK) الخاصة بموفِّر الهوية والمعروضة من مصدر موفِّر الهوية.
const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);
استبدِل TOKEN_GOES_HERE
برمزك المميّز.