پیادهسازی FedCM شامل چندین مرحله اصلی برای هر دو طرف ارائهدهنده هویت (IdP) و طرف متکی (RP) است. برای آشنایی با نحوه پیادهسازی FedCM در سمت RP ، به مستندات مراجعه کنید.
IdPها باید مراحل زیر را برای پیادهسازی FedCM انجام دهند:
- یک فایل شناخته شده ایجاد کنید.
- یک فایل پیکربندی ایجاد کنید.
- نقاط پایانی زیر را ایجاد کنید:
- وضعیت ورود کاربر را به مرورگر اطلاع دهید.
یک فایل شناخته شده ایجاد کنید
برای جلوگیری از سوءاستفاده ردیابها از API ، باید یک فایل شناختهشده از /.well-known/web-identity
مربوط به eTLD+1 مربوط به IdP ارائه شود.
فایل شناخته شده میتواند شامل ویژگیهای زیر باشد:
ملک | مورد نیاز | توضیحات |
---|---|---|
provider_urls | مورد نیاز | آرایهای از مسیرهای فایل پیکربندی IdP. در صورت مشخص شدن accounts_endpoint و login_url ، نادیده گرفته میشود (اما همچنان لازم است). |
accounts_endpoint | توصیه میشود، نیاز به login_url دارد | URL برای نقطه پایانی حسابها. این امکان پشتیبانی از پیکربندی چندگانه را فراهم میکند، مادامی که هر فایل پیکربندی از همان login_url و accounts_endpoint URL استفاده کند.توجه: این پارامتر از Chrome 132 پشتیبانی میشود. |
login_url | توصیه میشود، نیاز به accounts_endpoint دارد | آدرس اینترنتی صفحه ورود برای کاربر جهت ورود به IdP. این امکان پشتیبانی از پیکربندیهای متعدد را فراهم میکند، مادامی که هر فایل پیکربندی login_url و accounts_endpoint یکسانی استفاده کند.توجه: این پارامتر از کروم ۱۳۲ به بعد پشتیبانی میشود. |
برای مثال، اگر نقاط پایانی IdP تحت https://accounts.idp.example/
ارائه میشوند، باید علاوه بر یک فایل پیکربندی IdP ، یک فایل شناختهشده در https://idp.example/.well-known/web-identity
را نیز ارائه دهند. در اینجا نمونهای از محتوای فایل شناختهشده آورده شده است:
{
"provider_urls": ["https://accounts.idp.example/config.json"]
}
IdPها میتوانند با مشخص کردن accounts_endpoint
و login_url
در فایل شناختهشده، چندین فایل پیکربندی را برای یک IdP در خود جای دهند. این ویژگی میتواند در این موارد مفید باشد:
- یک IdP باید از چندین پیکربندی مختلف تست و تولید پشتیبانی کند.
- یک IdP باید از پیکربندیهای مختلف در هر منطقه پشتیبانی کند (برای مثال،
eu-idp.example
وus-idp.example
).
برای پشتیبانی از پیکربندیهای چندگانه (برای مثال، برای تمایز قائل شدن بین محیط تست و محیط عملیاتی)، IdP باید 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"
}
ایجاد فایل پیکربندی IdP و نقاط پایانی
فایل پیکربندی IdP فهرستی از نقاط پایانی مورد نیاز برای مرورگر را ارائه میدهد. IdPها باید میزبان یک یا چند فایل پیکربندی و نقاط پایانی و URLهای مورد نیاز باشند. تمام پاسخهای JSON باید با نوع محتوای application/json
ارائه شوند.
آدرس اینترنتی (URL) فایل پیکربندی توسط مقادیر ارائه شده به فراخوانی navigator.credentials.get()
که روی یک RP اجرا میشود، تعیین میشود. RP آدرس اینترنتی فایل پیکربندی را برای هر ارائهدهنده هویت ارسال میکند:
// 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
دریافت میکند. این درخواست کوکی ندارد و از ریدایرکتها پیروی نمیکند. این امر عملاً مانع از آن میشود که IdP متوجه شود چه کسی درخواست را ارسال کرده و کدام RP سعی در اتصال دارد. به عنوان مثال:
GET /config.json HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Sec-Fetch-Dest: webidentity
IdP باید یک نقطه پایانی پیکربندی پیادهسازی کند که با JSON پاسخ دهد. JSON شامل ویژگیهای زیر است:
ملک | توضیحات |
---|---|
accounts_endpoint (الزامی) | آدرس اینترنتی (URL) برای نقطه پایانی حسابها . |
account_label (اختیاری) | رشته برچسب حساب سفارشی، تعیین میکند که کدام حسابها هنگام استفاده از این فایل پیکربندی باید بازگردانده شوند، برای مثال: "account_label": "developer" .یک IdP میتواند برچسبگذاری حساب سفارشی را به صورت زیر پیادهسازی کند:
برای مثال، یک IdP فایل پیکربندی "https://idp.example/developer-config.json" را با مشخص کردن "account_label": "developer" پیادهسازی میکند. IdP همچنین برخی از حسابها را با استفاده از پارامتر label_hints در نقطه پایانی حسابها ، با برچسب "developer" علامتگذاری میکند. هنگامی که یک RP تابع navigator.credentials.get() را با مشخص کردن فایل پیکربندی "https://idp.example/developer-config.json" فراخوانی میکند، فقط حسابهایی با برچسب "developer" بازگردانده میشوند.توجه: برچسبهای حساب کاربری سفارشی از کروم ۱۳۲ پشتیبانی میشوند. |
supports_use_other_account (اختیاری) | مقدار بولی که مشخص میکند آیا کاربر میتواند با حسابی غیر از حسابی که با آن وارد سیستم شده است، وارد سیستم شود یا خیر (اگر IdP از چندین حساب پشتیبانی کند). این فقط در حالت فعال اعمال میشود. |
client_metadata_endpoint (اختیاری) | URL برای نقطه پایانی فراداده کلاینت . |
id_assertion_endpoint (الزامی) | آدرس اینترنتی (URL) برای نقطه پایانیِ ادعای شناسه . |
disconnect (اختیاری) | نشانی اینترنتی (URL) برای نقطه پایانی قطع ارتباط . |
login_url (الزامی) | آدرس اینترنتی صفحه ورود برای کاربر جهت ورود به IdP. |
branding (اختیاری) | شیء که شامل گزینههای مختلف برندسازی است. |
branding.background_color (اختیاری) | گزینهی Branding که رنگ پسزمینهی دکمهی «ادامه به عنوان...» را تنظیم میکند. از سینتکس CSS مربوطه، یعنی hex-color ، hsl() ، rgb() یا named-color استفاده کنید. |
branding.color (اختیاری) | گزینهی برندسازی که رنگ متن دکمهی «ادامه به عنوان...» را تنظیم میکند. از سینتکس CSS مربوطه، یعنی hex-color ، hsl() ، rgb() یا named-color استفاده کنید. |
branding.icons (اختیاری) | آرایهای از اشیاء آیکون. این آیکونها در پنجرهی ورود نمایش داده میشوند. شیء آیکون دو پارامتر دارد:
|
در اینجا یک نمونه از بدنه پاسخ از IdP آورده شده است:
{
"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 از چندین حساب کاربری یا جایگزینی حساب موجود پشتیبانی کند، کاربران میتوانند به حسابی غیر از حسابی که با آن وارد سیستم شدهاند، تغییر دهند.
برای اینکه کاربر بتواند حسابهای کاربری دیگری را انتخاب کند، IdP باید این ویژگی را در فایل پیکربندی مشخص کند:
{
"accounts_endpoint" : "/accounts.example",
"supports_use_other_account": true
}
نقطه پایانی حسابها
نقطه پایانی حسابهای IdP فهرستی از حسابهایی را که کاربر در IdP وارد آنها شده است، برمیگرداند. اگر IdP از چندین حساب پشتیبانی کند، این نقطه پایانی تمام حسابهای وارد شده را برمیگرداند.
مرورگر یک درخواست GET
با کوکیهایی با SameSite=None
ارسال میکند، اما بدون پارامتر client_id
، هدر Origin
یا هدر Referer
. این امر عملاً مانع از آن میشود که IdP بفهمد کاربر در کدام RP قصد ورود به سیستم را دارد. برای مثال:
GET /accounts.example HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
پس از دریافت درخواست، سرور باید:
- تأیید کنید که درخواست حاوی سرآیند HTTP
Sec-Fetch-Dest: webidentity
باشد. - کوکیهای جلسه را با شناسههای حسابهای کاربری که از قبل وارد سیستم شدهاند، مطابقت دهید.
- با لیست حسابها پاسخ دهید.
مرورگر انتظار یک پاسخ JSON را دارد که شامل یک ویژگی accounts
با آرایهای از اطلاعات حساب با ویژگیهای زیر است:
ملک | توضیحات |
---|---|
id (الزامی) | شناسه منحصر به فرد کاربر. |
name | نام کامل کاربر بر اساس زبان و تنظیمات برگزیده او. توجه: از کروم ۱۴۱، حداقل یکی از پارامترهای name ، email ، username یا tel مورد نیاز است. در نسخههای قبلی کروم، هم name و هم email مورد نیاز هستند. |
username | نام کاربری که توسط کاربر انتخاب میشود. توجه: از کروم ۱۴۱، حداقل یکی از پارامترهای name ، email ، username یا tel الزامی است. |
email | آدرس ایمیل کاربر. توجه: از کروم ۱۴۱، حداقل یکی از پارامترهای name ، email ، username یا tel مورد نیاز است. در نسخههای قبلی کروم، هم name و هم email مورد نیاز هستند. |
tel | شماره تلفن کاربر. توجه: از کروم ۱۴۱، حداقل یکی از پارامترهای name ، email ، username یا tel الزامی است. |
picture (اختیاری) | آدرس اینترنتی (URL) تصویر آواتار کاربر. |
given_name (اختیاری) | نام داده شده به کاربر. |
approved_clients (اختیاری) | آرایهای از شناسههای کلاینت RP که کاربر با آنها ثبتنام کرده است. |
login_hints (اختیاری) | آرایهای از تمام انواع فیلترهای ممکن که IdP برای مشخص کردن یک حساب کاربری پشتیبانی میکند. RP میتواند navigator.credentials.get() را با ویژگی loginHint فراخوانی کند تا به صورت انتخابی حساب کاربری مشخص شده را نمایش دهد. |
domain_hints (اختیاری) | آرایهای از تمام دامنههایی که حساب به آنها مرتبط است. RP میتواند navigator.credentials.get() را با یک ویژگی domainHint برای فیلتر کردن حسابها فراخوانی کند. |
label_hints (اختیاری) | آرایهای از رشتهها، برچسبهای حساب سفارشی که یک حساب به آنها مرتبط است. یک IdP میتواند برچسبگذاری حساب سفارشی را به صورت زیر پیادهسازی کند:
برای مثال، یک IdP فایل پیکربندی https://idp.example/developer-config.json را با مشخص کردن "account_label": "developer" پیادهسازی میکند. IdP همچنین برخی از حسابها را با استفاده از پارامتر label_hints در نقطه پایانی حسابها با برچسب "developer" علامتگذاری میکند. هنگامی که یک RP تابع navigator.credentials.get() را با فایل پیکربندی https://idp.example/developer-config.json مشخص شده فراخوانی میکند، فقط حسابهایی با برچسب "developer" بازگردانده میشوند.برچسبهای حساب کاربری سفارشی با Login Hint و Domain Hint متفاوت هستند، به این صورت که کاملاً توسط سرور IdP نگهداری میشوند و RP فقط فایل پیکربندی مورد استفاده را مشخص میکند. توجه: برچسبهای حساب کاربری سفارشی از کروم ۱۳۲ پشتیبانی میشوند. |
نمونه بدنه پاسخ:
{
"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
(غیرمجاز) پاسخ دهید.
لیست حسابهای برگردانده شده توسط مرورگر مصرف میشود و برای RP در دسترس نخواهد بود.
نقطه پایانی ادعای شناسه
نقطه پایانیِ ادعای شناسهی IdP، یک ادعا برای کاربر وارد شده به سیستم برمیگرداند. وقتی کاربر با استفاده از فراخوانی navigator.credentials.get()
وارد یک وبسایت RP میشود، مرورگر یک درخواست POST
با کوکیهایی با SameSite=None
و یک نوع محتوا از application/x-www-form-urlencoded
به این نقطه پایانی با اطلاعات زیر ارسال میکند:
ملک | توضیحات |
---|---|
client_id (الزامی) | شناسه کلاینت RP. |
account_id (الزامی) | شناسه منحصر به فرد کاربر در حال ورود. |
disclosure_text_shown | نتیجه رشتهای از "true" یا "false" (به جای یک مقدار بولی) است. در این موارد نتیجه "false" است:
|
disclosure_shown_for | فیلدهایی را که مرورگر در متن افشا به کاربر نشان داده است، فهرست میکند تا به کاربر اطلاع دهد که RP کدام دادهها را از IdP درخواست میکند. |
is_auto_selected | اگر احراز هویت مجدد خودکار روی RP انجام شود، is_auto_selected "true" را نشان میدهد. در غیر این صورت "false" . این برای پشتیبانی از ویژگیهای امنیتی بیشتر مفید است. به عنوان مثال، برخی از کاربران ممکن است سطح امنیتی بالاتری را ترجیح دهند که نیاز به میانجیگری صریح کاربر در احراز هویت دارد. اگر یک IdP درخواست توکن را بدون چنین میانجیگری دریافت کند، میتواند درخواست را به طور متفاوتی مدیریت کند. به عنوان مثال، یک کد خطا را طوری برگرداند که RP بتواند API FedCM را دوباره با mediation: required . |
fields (اختیاری) | آرایهای از رشتهها که اطلاعات کاربری را که RP از IdP درخواست اشتراکگذاری آن را کرده است، مشخص میکند. فیلدهای زیر میتوانند به صورت اختیاری مشخص شوند:
fields ، disclosure_text_shown و disclosure_shown_for را برای فهرست کردن فیلدهای مشخص شده در درخواست POST، مانند مثال زیر ، ارسال خواهد کرد.نکته: رابط برنامهنویسی کاربردی فیلدها (Fields API) توسط کروم ۱۳۲ و بالاتر پشتیبانی میشود. فیلدهای «نام کاربری» (username) و «تلفن» (tel) از کروم ۱۴۱ پشتیبانی میشوند. |
params (اختیاری) | هر شیء JSON معتبری که امکان تعیین پارامترهای کلید-مقدار سفارشی اضافی را فراهم میکند، برای مثال:
params به JSON سریالایز شده و سپس به صورت percent-encoded نمایش داده میشود.توجه: API پارامترها توسط کروم ۱۳۲ و بالاتر پشتیبانی میشود. |
مثال هدر 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¶ms=%22%7B%5C%22nonce%5C%22%3A%5C%22nonce-value%5C%22%7D%22.%0D%0A4&fields=email,picture&disclosure_shown_for=email,picture
پس از دریافت درخواست، سرور باید:
- با CORS (اشتراکگذاری منابع بین مبدائی) به درخواست پاسخ دهید.
- تأیید کنید که درخواست حاوی سرآیند HTTP
Sec-Fetch-Dest: webidentity
باشد. - هدر
Origin
را با مبدا RP تعیین شده توسطclient_id
مطابقت دهید. در صورت عدم تطابق، رد کنید. - شناسه
account_id
با شناسه حساب کاربری که از قبل وارد سیستم شده است، مطابقت دهید. در صورت عدم تطابق، آن را رد کنید. - با یک توکن پاسخ دهید. اگر درخواست رد شد، با یک پاسخ خطا پاسخ دهید.
IdP میتواند تصمیم بگیرد که چگونه توکن را صادر کند. به طور کلی، با اطلاعاتی مانند شناسه حساب، شناسه مشتری، مبدا صادرکننده و nonce امضا میشود تا RP بتواند اصالت توکن را تأیید کند.
مرورگر انتظار یک پاسخ JSON شامل ویژگی زیر را دارد:
ملک | توضیحات |
---|---|
token | توکن رشتهای است که شامل ادعاهایی در مورد احراز هویت است. |
continue_on | آدرس اینترنتی (URL) ریدایرکت که امکان ورود چند مرحلهای را فراهم میکند. |
توکن برگردانده شده توسط مرورگر به RP ارسال میشود تا RP بتواند احراز هویت را تأیید کند.
{
// IdP can respond with a token to authenticate the user
"token": "***********"
}
ادامه در ویژگی
IdP میتواند یک URL تغییر مسیر در پاسخ نقطه پایانی ادعای شناسه ارائه دهد تا جریان ورود چند مرحلهای را فعال کند. این زمانی مفید است که IdP نیاز به درخواست اطلاعات یا مجوزهای اضافی داشته باشد، به عنوان مثال:
- اجازه دسترسی به منابع سمت سرور کاربر.
- تأیید بهروز بودن اطلاعات تماس.
- کنترلهای والدین.
نقطه پایانیِ ادعای شناسه میتواند یک ویژگی 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 dialog window:
"continue_on": "https://idp.example/continue_on_url"
}
اگر پاسخ شامل پارامتر continue_on
باشد، یک پنجره محاورهای جدید باز میشود و کاربر را به مسیر مشخص شده هدایت میکند. پس از تعامل کاربر با صفحه continue_on
، IdP باید IdentityProvider.resolve()
با توکن ارسالی به عنوان آرگومان فراخوانی کند تا promise حاصل از فراخوانی 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);
});
سپس مرورگر به طور خودکار پنجره گفتگو را میبندد و توکن را به فراخواننده API برمیگرداند. فراخوانی یکباره IdentityProvider.resolve()
تنها راه ارتباط پنجره والد (RP) و پنجره گفتگو (IdP) است.
اگر کاربر درخواست را رد کند، IdP میتواند با فراخوانی IdentityProvider.close()
پنجره را ببندد.
IdentityProvider.close();
API Continuation برای عملکرد خود به تعامل صریح کاربر (کلیک) نیاز دارد. در اینجا نحوه عملکرد API Continuation با حالتهای مختلف میانجیگری آمده است:
- در حالت
passive
:-
mediation: 'optional'
(پیشفرض): API Continuation فقط با یک حرکت کاربر، مانند کلیک روی یک دکمه در صفحه یا در رابط کاربری FedCM، کار خواهد کرد. هنگامی که احراز هویت مجدد خودکار بدون حرکت کاربر فعال میشود، هیچ پنجره محاورهای باز نمیشود و promise رد میشود. -
mediation: 'required'
: همیشه از کاربر میخواهد که تعامل داشته باشد، بنابراین API Continuation همیشه کار میکند.
-
- در حالت فعال :
- فعالسازی کاربر همیشه الزامی است. API Continuation همیشه سازگار است.
اگر به هر دلیلی کاربر حساب کاربری خود را در کادر محاورهای تغییر داده باشد (برای مثال، IdP تابع "استفاده از حساب کاربری دیگر" را ارائه میدهد، یا در موارد واگذاری اختیار)، فراخوانی resolve یک آرگومان دوم اختیاری میگیرد که امکان انجام کاری مانند موارد زیر را فراهم میکند:
IdentityProvider.resolve(token, {accountId: '1234');
پاسخ خطا را برگردانید
id_assertion_endpoint
همچنین میتواند یک پاسخ "خطا" را برگرداند که دارای دو فیلد اختیاری است:
-
code
: IdP میتواند یکی از خطاهای شناختهشده را از لیست خطاهای مشخصشده توسط OAuth 2.0 (invalid_request
،unauthorized_client
،access_denied
،server_error
وtemporarily_unavailable
) انتخاب کند یا از هر رشته دلخواهی استفاده کند. در صورت انتخاب مورد دوم، کروم رابط کاربری خطا را با یک پیام خطای عمومی رندر کرده و کد را به RP ارسال میکند. -
url
: این فیلد یک صفحه وب قابل خواندن توسط انسان را با اطلاعاتی در مورد خطا شناسایی میکند تا اطلاعات بیشتری در مورد خطا به کاربران ارائه دهد. این فیلد برای کاربران مفید است زیرا مرورگرها نمیتوانند پیامهای خطای غنی را در یک رابط کاربری داخلی ارائه دهند. به عنوان مثال: لینکهایی برای مراحل بعدی یا اطلاعات تماس خدمات مشتری. اگر کاربری بخواهد در مورد جزئیات خطا و نحوه رفع آن اطلاعات بیشتری کسب کند، میتواند برای جزئیات بیشتر به صفحه ارائه شده از رابط کاربری مرورگر مراجعه کند. URL باید از همان سایت IdPconfigURL
باشد.
// id_assertion_endpoint response
{
"error" : {
"code": "access_denied",
"url" : "https://idp.example/error?type=access_denied"
}
}
برچسبهای حساب سفارشی
با برچسبهای حساب کاربری سفارشی ، IdP میتواند حسابهای کاربری را با برچسبها حاشیهنویسی کند و RP میتواند با مشخص کردن configURL
برای آن برچسب خاص، فقط حسابهایی با برچسبهای خاص را دریافت کند. این میتواند زمانی مفید باشد که یک RP نیاز به فیلتر کردن حسابها بر اساس معیارهای خاص داشته باشد، به عنوان مثال، فقط حسابهای خاص نقش مانند "developer"
یا "hr"
را نمایش دهد.
فیلترینگ مشابهی با استفاده از ویژگیهای Domain Hint و Login Hint ، با مشخص کردن آنها در فراخوانی navigator.credentials.get()
امکانپذیر است. با این حال، برچسبهای حساب کاربری سفارشی میتوانند کاربران را با مشخص کردن فایل پیکربندی فیلتر کنند، که به ویژه هنگامی که از چندین configURL استفاده میشود، مفید است. برچسبهای حساب کاربری سفارشی همچنین از این نظر متفاوت هستند که از سرور IdP ارائه میشوند، برخلاف RP، مانند login یا domain hints.
یک IdP را در نظر بگیرید که میخواهد بین حسابهای "developer"
و "hr"
تمایز قائل شود. برای دستیابی به این هدف، IdP باید از دو 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"
}
- با چنین تنظیماتی، فایل شناختهشده باید شامل
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
) لیستی از حسابها را برمیگرداند که شامل یک ویژگی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"]
}]
}
وقتی یک RP میخواهد به کاربران "hr"
اجازه ورود به سیستم را بدهد، میتواند configURL https://idp.example/hr/fedcm.json
را در فراخوانی 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 در این سایت پشتیبانی نمیشود، دریافت نکند.
ملاحظات اضافی:
- برچسبها رشته هستند. اگر آرایه
label_hints
یا فیلدaccount_label
از مقداری غیر از رشته استفاده کند، آن مقدار نادیده گرفته میشود. - اگر هیچ برچسبی در
configURL
مشخص نشده باشد، همه حسابها در انتخابگر حساب FedCM نمایش داده میشوند. - اگر هیچ برچسبی برای یک حساب کاربری مشخص نشده باشد، این حساب کاربری فقط در انتخابگر حساب کاربری نمایش داده میشود، در صورتی که
configURL
نیز برچسبی مشخص نکرده باشد. - اگر در حالت غیرفعال (مشابه ویژگی Domain Hint) هیچ حسابی با برچسب درخواستی مطابقت نداشته باشد، پنجرهی FedCM یک اعلان ورود به سیستم نشان میدهد که به کاربر اجازه میدهد وارد یک حساب IdP شود. برای حالت فعال، پنجرهی ورود به سیستم مستقیماً باز میشود.
قطع اتصال نقطه پایانی
با فراخوانی IdentityCredential.disconnect()
، مرورگر یک درخواست POST
از نوع cross-origin با کوکیهایی با SameSite=None
و نوع محتوای application/x-www-form-urlencoded
به این نقطه پایانی disconnect با اطلاعات زیر ارسال میکند:
ملک | توضیحات |
---|---|
account_hint | یک راهنمایی برای حساب IdP.. |
client_id | شناسه کلاینت RP. |
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
پس از دریافت درخواست، سرور باید:
- با CORS (اشتراکگذاری منابع بین مبدائی) به درخواست پاسخ دهید.
- تأیید کنید که درخواست حاوی سرآیند HTTP
Sec-Fetch-Dest: webidentity
باشد. - هدر
Origin
را با مبدا RP تعیین شده توسطclient_id
مطابقت دهید. در صورت عدم تطابق، رد کنید. -
account_hint
با شناسههای حسابهای کاربری که از قبل وارد سیستم شدهاند، مطابقت بده. - حساب کاربری را از RP جدا کنید.
- اطلاعات حساب کاربری شناساییشده را با فرمت JSON به مرورگر پاسخ دهید.
یک نمونه از پاسخ JSON payload به این شکل است:
{
"account_id": "account456"
}
در عوض، اگر IdP بخواهد مرورگر تمام حسابهای مرتبط با RP را قطع کند، رشتهای را ارسال کنید که با هیچ شناسه حسابی مطابقت نداشته باشد، به عنوان مثال "*"
.
نقطه پایانی فراداده کلاینت
نقطه پایانی فراداده کلاینت IdP، فرادادههای طرف اتکاکننده مانند سیاست حفظ حریم خصوصی، شرایط خدمات و نمادهای لوگوی RP را برمیگرداند. RPها باید از قبل پیوندهایی به سیاست حفظ حریم خصوصی و شرایط خدمات خود را به IdP ارائه دهند. این پیوندها در پنجره ورود به سیستم نمایش داده میشوند، زمانی که کاربر هنوز در 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
پس از دریافت درخواست، سرور باید:
- RP مربوط به
client_id
را تعیین کنید. - با استفاده از فرادادههای کلاینت پاسخ دهید.
ویژگیهای مربوط به نقطه پایانی فراداده کلاینت عبارتند از:
ملک | توضیحات |
---|---|
privacy_policy_url (اختیاری) | آدرس اینترنتی سیاست حفظ حریم خصوصی RP. |
terms_of_service_url (اختیاری) | آدرس اینترنتی شرایط خدمات RP. |
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
}]
}
متادیتای کلاینت بازگردانده شده توسط مرورگر مصرف میشود و برای RP در دسترس نخواهد بود.
آدرس ورود
این نقطه پایانی برای ورود کاربر به IdP استفاده میشود.
با استفاده از API وضعیت ورود ، IdP باید وضعیت ورود کاربر را به مرورگر اطلاع دهد. با این حال، وضعیت میتواند ناهمگام باشد، مانند زمانی که جلسه منقضی میشود . در چنین سناریویی، مرورگر میتواند به صورت پویا به کاربر اجازه دهد از طریق URL صفحه ورود مشخص شده با login_url
فایل پیکربندی idp، وارد IdP شود.
همانطور که در تصویر زیر نشان داده شده است، پنجرهی FedCM پیامی را نمایش میدهد که پیشنهاد ورود به سیستم را میدهد.

وقتی کاربر روی دکمه ادامه کلیک میکند، مرورگر یک پنجره محاورهای برای صفحه ورود IdP باز میکند.

این پنجرهی محاورهای، یک پنجرهی مرورگر معمولی است که کوکیهای شخص اول را در خود جای داده است. هر اتفاقی که در این پنجره رخ دهد، به IdP بستگی دارد و هیچ کنترل پنجرهای برای ارسال درخواست ارتباط بین مبدا و مقصد به صفحهی RP در دسترس نیست. پس از ورود کاربر، IdP باید:
- هدر
Set-Login: logged-in
ارسال کنید یا APInavigator.login.setStatus("logged-in")
را فراخوانی کنید تا به مرورگر اطلاع دهید که کاربر وارد سیستم شده است. - برای بستن کادر محاورهای، تابع
IdentityProvider.close()
را فراخوانی کنید.
وضعیت ورود کاربر را به مرورگر اطلاع دهید
API وضعیت ورود، مکانیزمی است که در آن یک وبسایت، به خصوص یک IdP، وضعیت ورود کاربر به IdP را به مرورگر اطلاع میدهد. با این API، مرورگر میتواند درخواستهای غیرضروری به IdP را کاهش داده و حملات احتمالی زمانبندی را کاهش دهد .
IdPها میتوانند وضعیت ورود کاربر را با ارسال یک هدر HTTP یا با فراخوانی یک API جاوا اسکریپت، هنگامی که کاربر در IdP وارد سیستم میشود یا هنگامی که کاربر از تمام حسابهای IdP خود خارج میشود، به مرورگر اطلاع دهند. برای هر IdP (که با URL پیکربندی آن مشخص میشود)، مرورگر یک متغیر سه حالته را نگه میدارد که وضعیت ورود را با مقادیر ممکن نشان میدهد:
-
logged-in
-
logged-out
-
unknown
(پیشفرض)
وضعیت ورود | توضیحات |
---|---|
logged-in | وقتی وضعیت ورود کاربر روی logged-in تنظیم شده باشد، RP که FedCM را فراخوانی میکند، درخواستهایی را به نقطه پایانی حسابهای IdP ارسال میکند و حسابهای موجود را در کادر محاورهای FedCM به کاربر نمایش میدهد. |
logged-out | وقتی وضعیت ورود کاربر logged-out باشد، فراخوانی بیصدای FedCM بدون ارسال درخواست به نقطه پایانی حسابهای IdP با شکست مواجه میشود. |
unknown (پیشفرض) | وضعیت unknown قبل از اینکه IdP با استفاده از API وضعیت ورود، سیگنالی ارسال کند، تنظیم میشود. وقتی وضعیت unknown است، مرورگر درخواستی به نقطه پایانی حسابهای IdP ارسال میکند و وضعیت را بر اساس پاسخ از نقطه پایانی حسابها بهروزرسانی میکند. |
برای نشان دادن اینکه کاربر وارد سیستم شده است، یک هدر HTTP Set-Login: logged-in
در یک ناوبری سطح بالا یا یک درخواست زیرمنبع در همان سایت در مبدا IdP ارسال کنید:
Set-Login: logged-in
روش دیگر، فراخوانی متد جاوا اسکریپت navigator.login.setStatus('logged-in')
از مبدا IdP در یک ناوبری سطح بالا است:
navigator.login.setStatus('logged-in')
وضعیت ورود کاربر به صورت logged-in
تنظیم خواهد شد.
برای اینکه نشان دهید کاربر از تمام حسابهای کاربری خود خارج شده است، یک هدر HTTP Set-Login: logged-out
در یک نوار ناوبری سطح بالا یا یک درخواست subresource در همان سایت در مبدا IdP ارسال کنید:
Set-Login: logged-out
روش دیگر، فراخوانی API جاوا اسکریپت navigator.login.setStatus('logged-out')
از مبدا IdP در یک ناوبری سطح بالا است:
navigator.login.setStatus('logged-out')
وضعیت ورود کاربر به صورت logged-out
تنظیم خواهد شد.
وضعیت unknown
قبل از اینکه IdP با استفاده از API وضعیت ورود، سیگنالی ارسال کند، تنظیم میشود. مرورگر درخواستی را به نقطه پایانی حسابهای IdP ارسال میکند و وضعیت را بر اساس پاسخ از نقطه پایانی حسابها بهروزرسانی میکند:
- اگر نقطه پایانی لیستی از حسابهای فعال را برگرداند، وضعیت را به
logged-in
بهروزرسانی کنید و کادر محاورهای FedCM را باز کنید تا آن حسابها نمایش داده شوند. - اگر نقطه پایانی هیچ حسابی را برنمیگرداند، وضعیت را به
logged-out
بهروزرسانی کنید و فراخوانی FedCM را با شکست مواجه کنید.
اجازه دهید کاربر از طریق یک جریان ورود پویا وارد سیستم شود
اگرچه IdP مدام وضعیت ورود کاربر را به مرورگر اطلاع میدهد، اما ممکن است از همگامسازی خارج شده باشد، مثلاً زمانی که جلسه منقضی میشود. مرورگر سعی میکند وقتی وضعیت ورود به سیستم logged-in
است، یک درخواست اعتبارسنجی به نقطه پایانی حسابها ارسال کند، اما سرور هیچ حسابی را برنمیگرداند زیرا جلسه دیگر در دسترس نیست. در چنین سناریویی، مرورگر میتواند به صورت پویا به کاربر اجازه دهد از طریق یک پنجره محاورهای به IdP وارد شود .