מדריך למפתחים בנושא Federated Credential Management API

למדו כיצד להשתמש ב-FedCM לאיחוד שירותי אימות הזהות תוך שמירה על פרטיות.

FedCM (Federated Credential Management) הוא גישה ששומרת על הפרטיות בשירותי זהות מאוחדים (כמו 'כניסה באמצעות...') שמאפשרת למשתמשים להתחבר לאתרים בלי לשתף את הפרטים האישיים שלהם עם שירות הזהויות או עם האתר.

לקבלת מידע נוסף על תרחישים לדוגמה, תהליכי עבודה של משתמשים ומפת דרכים של API, קראו את המבוא ל-FedCM API.

סביבת הפיתוח של FedCM

כדי להשתמש ב-FedCM, נדרש הקשר מאובטח (HTTPS או מארח מקומי) גם ב-IdP וגם ב-RP ב-Chrome.

קוד ניפוי באגים ב-Chrome ב-Android

הגדרה והפעלה של שרת באופן מקומי לניפוי באגים בקוד FedCM. אפשר לגשת לשרת הזה ב-Chrome במכשיר Android שמחובר באמצעות כבל USB עם הכוונה ליציאה אחרת.

אפשר להשתמש בכלי הפיתוח במחשב כדי לנפות באגים ב-Chrome ב-Android. לשם כך, פועלים לפי ההוראות במאמר ניפוי באגים מרחוק במכשירי Android.

חסימת קובצי cookie של צד שלישי ב-Chrome

הדמיה של הפסקת הדרגתית של קובצי cookie של צד שלישי על ידי הגדרת Chrome כך שיחסום אותם
סימולציה הדרגתית של קובצי cookie של צד שלישי על ידי הגדרת Chrome כך שיחסום אותם

אפשר לבדוק איך FedCM פועל ללא קובצי cookie של צד שלישי ב-Chrome לפני האכיפה בפועל.

כדי לחסום קובצי Cookie של צד שלישי, צריך להשתמש במצב פרטי או לבחור באפשרות 'חסימת קובצי Cookie של צד שלישי' בהגדרות של שולחן העבודה בכתובת chrome://settings/cookies או בנייד על ידי מעבר אל הגדרות > הגדרות אתר > קובצי Cookie.

שימוש ב-FedCM API

השילוב עם FedCM יוצר קובץ ידוע, קובץ תצורה ונקודות קצה עבור רשימת חשבונות, הפקת טענת נכוֹנוּת (assertion), ואם רוצים, גם מטא-נתונים של לקוח.

לאחר מכן, FedCM חושף את ממשקי ה-API של JavaScript שגורמים מוגבלים יכולים להשתמש בהם כדי להיכנס באמצעות ה-IdP.

יצירת קובץ מוכר

כדי למנוע מכלי מעקב לנצל לרעה את ה-API, צריך להגיש קובץ ידוע מ-/.well-known/web-identity של eTLD+1 של ה-IdP.

לדוגמה, אם נקודות הקצה של IdP מוצגות תחת https://accounts.idp.example/, הן צריכות להציג קובץ ידוע ב-https://idp.example/.well-known/web-identity וגם קובץ תצורה של IdP. דוגמה לתוכן מוכר של קובץ:

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

קובץ ה-JSON צריך להכיל את המאפיין provider_urls עם מערך של כתובות URL של קובץ תצורת IdP, שניתן לציין אותן כחלק מנתיב configURL ב-navigator.credentials.get על ידי גורמים מוגבלים. מספר המחרוזות של כתובות ה-URL במערך מוגבל לאחת, אבל הוא עשוי להשתנות עם המשוב שלכם בעתיד.

יצירת קובץ תצורה ונקודות קצה ל-IdP

קובץ התצורה של IdP מספק רשימה של נקודות הקצה הנדרשות לדפדפן. מזהי ה-IdP יארחו את קובץ התצורה הזה ואת נקודות הקצה וכתובות ה-URL הנדרשות. כל תגובות ה-JSON צריך להישלח עם סוג התוכן application/json.

כתובת ה-URL של קובץ התצורה נקבעת לפי הערכים שסופקו לקריאה ל-navigator.credentials.get שבוצעה ב-RP.

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

צריך לציין כתובת URL מלאה של מיקום קובץ התצורה של IdP בתור configURL. כאשר מתבצעת קריאה ל-navigator.credentials.get() ב-RP, הדפדפן מאחזר את קובץ התצורה באמצעות בקשת GET ללא הכותרת Origin או הכותרת Referer. הבקשה לא כוללת קובצי cookie והיא לא עוקבת אחר הפניות אוטומטיות. כך ה-IdP לא יוכל לדעת מי שלח את הבקשה ואיזה גורם מוגבל (RP) מנסה להתחבר. למשל:

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

הדפדפן מצפה לתגובת JSON מה-IdP, שכולל את המאפיינים הבאים:

מאפיין (property) תיאור
accounts_endpoint (חובה) כתובת ה-URL של נקודת הקצה של חשבונות.
ֶclient_metadata_endpoint (אופציונלי) כתובת ה-URL של נקודת הקצה מטא-נתונים של לקוח.
id_assertion_endpoint (חובה) כתובת ה-URL של נקודת הקצה של טענת נכוֹנוּת (assertion) של המזהה.
ֶdisconnect (אופציונלי) כתובת ה-URL של נקודת הקצה ניתוק.
login_url (חובה) כתובת ה-URL של דף ההתחברות, שבו המשתמש יכול להיכנס ל-IdP.
ֶ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 או שווה לו.

גורם מוגבל (RP) יכול לשנות את המחרוזת בממשק המשתמש של תיבת הדו-שיח של FedCM באמצעות הערך identity.context עבור navigator.credentials.get(), כדי להתאים להקשרים של אימות מוגדרים מראש. הנכס האופציונלי יכול להיות אחד מהערכים "signin" (ברירת המחדל), "signup", "use" או "continue".

איך מיתוג חל על תיבת הדו-שיח של FedCM
איך מחילים מיתוג בתיבת הדו-שיח של FedCM

הנה דוגמה לגוף תשובה מה-IdP:

{
  "accounts_endpoint": "/accounts.php",
  "client_metadata_endpoint": "/client_metadata.php",
  "id_assertion_endpoint": "/assertion.php",
  "disconnect_endpoint": "/disconnect.php",
  "login_url": "/login",
  "branding": {
    "background_color": "green",
    "color": "#FFEEAA",
    "icons": [{
      "url": "https://idp.example/icon.ico",
      "size": 25
    }]
  }
}

אחרי שהדפדפן מאחזר את קובץ התצורה, הוא שולח בקשות נוספות לנקודות הקצה של IdP:

נקודות הקצה ב-IdP
נקודות קצה של IdP

נקודת קצה של חשבונות

נקודת הקצה של חשבונות ה-IdP מחזירה רשימה של חשבונות שהמשתמש מחובר אליהם ב-IdP. אם ה-IdP תומך במספר חשבונות, נקודת הקצה הזו תחזיר את כל החשבונות שמחוברים.

הדפדפן שולח בקשת GET עם קובצי cookie עם SameSite=None, אבל בלי הפרמטר client_id, הכותרת Origin או הכותרת Referer. כך ה-IdP לא יוכל לדעת לאיזה גורם מוגבל (RP) המשתמש מנסה להיכנס. למשל:

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

לאחר קבלת הבקשה, השרת צריך:

  1. צריך לוודא שהבקשה מכילה כותרת HTTP מסוג Sec-Fetch-Dest: webidentity.
  2. מתאימים את קובצי ה-Cookie של הסשן למזהים של החשבונות שכבר מחוברים.
  3. משיבים עם רשימת החשבונות.

הדפדפן מצפה לתגובת JSON שכוללת נכס accounts עם מגוון פרטי חשבון עם המאפיינים הבאים:

מאפיין (property) תיאור
id (חובה) המזהה הייחודי של המשתמש.
name (חובה) השם הפרטי ושם המשפחה של המשתמש.
email (חובה) כתובת האימייל של המשתמש.
ֶgiven_name (אופציונלי) השם הפרטי של המשתמש.
ֶpicture (אופציונלי) כתובת ה-URL של תמונת הדמות של המשתמש.
ֶapproved_clients (אופציונלי) מערך של מזהי לקוחות RP שאיתם המשתמש נרשם.
ֶlogin_hints (אופציונלי) מערך של כל סוגי המסננים האפשריים שה-IdP תומך בהם כדי לציין חשבון. ה-RP יכול להפעיל את navigator.credentials.get() באמצעות המאפיין loginHint כדי להציג באופן סלקטיבי את החשבון שצוין.
ֶdomain_hints (אופציונלי) מערך של כל הדומיינים שהחשבון משויך אליהם. ה-RP יכול להפעיל את navigator.credentials.get() באמצעות המאפיין domainHint כדי לסנן את החשבונות.

דוגמה לגוף התשובה:

{
  "accounts": [{
    "id": "1234",
    "given_name": "John",
    "name": "John Doe",
    "email": "john_doe@idp.example",
    "picture": "https://idp.example/profile/123",
    "approved_clients": ["123", "456", "789"],
    "login_hints": ["demo1", "demo1@idp.example"]
  }, {
    "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", "demo2@idp.example"],
    "domain_hints": ["corp.example"]
  }]
}

אם המשתמש לא מחובר, צריך להשיב ב-HTTP 401 (לא מורשה).

רשימת החשבונות שמוחזרת נצרכת על ידי הדפדפן ולא תהיה זמינה ל-RP.

נקודת קצה למטא-נתונים של לקוח

נקודת הקצה של המטא-נתונים של הלקוח ב-IdP מחזירה את המטא-נתונים של הצד הנסמך, כמו מדיניות הפרטיות והתנאים וההגבלות של ה-RP. הגורמים המוגבלים צריכים לספק מראש קישורים למדיניות הפרטיות ולתנאים ולהגבלות שלהם. הקישורים האלה מוצגים בתיבת הדו-שיח לכניסה אם המשתמש עדיין לא נרשם ב-RP עם ה-IdP.

הדפדפן שולח בקשת GET באמצעות client_id navigator.credentials.get ללא קובצי cookie. למשל:

GET /client_metadata.php?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. שליחת התשובה עם המטא-נתונים של הלקוח.

המאפיינים של נקודת הקצה במטא-נתונים של הלקוח כוללים:

מאפיין (property) תיאור
ֶprivacy_policy_url (אופציונלי) כתובת ה-URL של מדיניות הפרטיות RP.
ֶterms_of_service_url (אופציונלי) כתובת ה-URL של התנאים וההגבלות של הגורם המוגבל.

הדפדפן מצפה לתגובת JSON מנקודת הקצה:

{
  "privacy_policy_url": "https://rp.example/privacy_policy.html",
  "terms_of_service_url": "https://rp.example/terms_of_service.html",
}

המטא-נתונים של הלקוח שמוחזרים נצרכים על ידי הדפדפן ולא יהיו זמינים ל-RP.

נקודת קצה לטענת נכונות (assertion) של מזהה

נקודת הקצה של טענת נכוֹנוּת (assertion) של המזהה של ה-IdP מחזירה טענת נכוֹנוּת (assertion) של המשתמש המחובר. כשהמשתמש נכנס לאתר RP באמצעות קריאה ל-navigator.credentials.get(), הדפדפן שולח בקשת POST עם קובצי cookie עם SameSite=None ותוכן מסוג application/x-www-form-urlencoded לנקודת הקצה הזו, עם הפרטים הבאים:

מאפיין (property) תיאור
client_id (חובה) מזהה הלקוח של הגורם המוגבל.
account_id (חובה) המזהה הייחודי של המשתמש שנכנס.
ֶnonce (אופציונלי) הבקשה החד-פעמית, שסופקה על ידי הגורם המוגבל.
disclosure_text_shown התוצאה היא מחרוזת של "true" או "false" (במקום ערך בוליאני). אם טקסט הגילוי הנאות לא הוצג, התוצאה היא "false". מצב כזה קורה כשמזהה הלקוח של הגורם המוגבל (RP) נכלל ברשימת הנכסים approved_clients של התשובה מנקודת הקצה של החשבון, או אם הדפדפן זיהה רגע הרשמה בעבר כאשר לא צוין approved_clients.
is_auto_selected אם מתבצע אימות מחדש אוטומטי ב-RP, הערך is_auto_selected מציין את "true". אחרת, "false". האפשרות הזו עוזרת לתמוך בתכונות נוספות שקשורות לאבטחה. לדוגמה, יכול להיות שמשתמשים מסוימים יעדיפו רמת אבטחה גבוהה יותר, שמחייבת גישור מפורש של המשתמש באימות. אם IdP מקבל בקשת אסימון ללא גישור כזה, הוא עשוי לטפל בבקשה באופן שונה. לדוגמה, מחזירים קוד שגיאה שמאפשר ל-RP להפעיל שוב את FedCM API באמצעות mediation: required.

כותרת HTTP לדוגמה:

POST /assertion.php HTTP/1.1
Host: accounts.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=Ct60bD&disclosure_text_shown=true&is_auto_selected=true

לאחר קבלת הבקשה, השרת צריך:

  1. עונים לבקשה באמצעות CORS (שיתוף משאבים בין מקורות).
  2. צריך לוודא שהבקשה מכילה כותרת HTTP מסוג Sec-Fetch-Dest: webidentity.
  3. מתאימים בין הכותרת Origin לבין מקור ה-RP שנקבע על ידי client_id. אנחנו דוחים אם הם לא תואמים.
  4. התאמה של account_id למזהה של החשבון שכבר מחובר. דוחים אם הם לא תואמים.
  5. להשיב באמצעות אסימון. אם הבקשה נדחתה, צריך להשיב באמצעות תגובת שגיאה.

אופן ההנפקה של האסימון תלוי ב-IdP, אבל באופן כללי הוא חתום במידע כמו מספר החשבון, מספר הלקוח, מקור המנפיק nonce, כך שה-RP יכול לאמת שהאסימון אמיתי.

הדפדפן מצפה לתגובת JSON שכוללת את המאפיין הבא:

מאפיין (property) תיאור
token (חובה) אסימון הוא מחרוזת שכוללת הצהרות לגבי האימות.
{
  "token": "***********"
}

האסימון שמוחזר מועבר ל-RP על ידי הדפדפן כדי שה-RP יוכל לאמת את האימות.

החזרת הודעת שגיאה

הפרמטר id_assertion_endpoint יכול גם להחזיר תגובת 'שגיאה', שכוללת שני שדות אופציונליים:

  • code: ה-IdP יכול לבחור אחת מהשגיאות הידועות מרשימת השגיאות שצוינו ל-OAuth 2.0 (invalid_request, unauthorized_client, access_denied, server_error ו-temporarily_unavailable) או להשתמש במחרוזת שרירותית כלשהי. אם האפשרות השנייה, Chrome מעבד את ממשק המשתמש של השגיאה עם הודעת שגיאה גנרית ומעביר את הקוד ל-RP.
  • url: זהו דף אינטרנט שקריא לאנשים, עם מידע על השגיאה כדי לספק למשתמשים מידע נוסף על השגיאה. השדה הזה שימושי למשתמשים כי דפדפנים לא יכולים לספק הודעות שגיאה עשירות בממשק משתמש מותאם. לדוגמה, קישורים לשלבים הבאים, פרטים ליצירת קשר עם שירות הלקוחות וכו'. אם משתמש רוצה לקבל מידע נוסף על פרטי השגיאה ואיך לתקן אותה, הוא יכול להיכנס לדף שסופק דרך ממשק המשתמש של הדפדפן לקבלת פרטים נוספים. כתובת ה-URL חייבת להיות מאותו אתר כמו ה-IdP configURL.
// id_assertion_endpoint response
{
  "error" : {
     "code": "access_denied",
     "url" : "https://idp.example/error?type=access_denied"
  }
}

ניתוק נקודת הקצה

הפעלה של IdentityCredential.disconnect() תגרום לכך שהדפדפן ישלח בקשת POST ממקורות שונים עם קובצי cookie עם SameSite=None וסוג תוכן application/x-www-form-urlencoded לנקודת הקצה הניתוק הזו, עם הפרטים הבאים:

מאפיין (property) תיאור
account_hint רמז לחשבון ה-IdP..
client_id מזהה הלקוח של הגורם המוגבל.
POST /disconnect.php 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. צריך לוודא שהבקשה מכילה כותרת HTTP מסוג Sec-Fetch-Dest: webidentity.
  3. מתאימים בין הכותרת Origin לבין מקור ה-RP שנקבע על ידי client_id. אנחנו דוחים אם הם לא תואמים.
  4. התאמה של account_hint למזהים של החשבונות שכבר מחוברים.
  5. מנתקים את חשבון המשתמש מה-RP.
  6. הגב לדפדפן עם פרטי חשבון המשתמש שזוהו בפורמט JSON.

דוגמה למטען ייעודי (payload) של תגובה ב-JSON נראה כך:

{
  "account_id": "account456"
}

במקום זאת, אם ה-IdP רוצה שהדפדפן ינתק את כל החשבונות שמשויכים ל-RP, צריך להעביר מחרוזת שלא תואמת לאף מזהה חשבון, למשל "*".

כתובת URL לכניסה

באמצעות Login Status API, ה-IdP חייב לציין את סטטוס ההתחברות של המשתמש לדפדפן. עם זאת, יכול להיות שהסטטוס לא מסונכרן, למשל מתי פג תוקף הסשן. בתרחיש כזה, הדפדפן יכול לאפשר למשתמש באופן דינמי להיכנס ל-IdP דרך כתובת ה-URL של דף ההתחברות שצוינה ב-login_url של קובץ התצורה של ה-Idp.

בתיבת הדו-שיח של FedCM מוצגת הודעה שמציעה כניסה, כפי שמוצג בתמונה הבאה.

A
תיבת דו-שיח של FedCM עם הצעה להיכנס ל-IdP.

כשהמשתמש לוחץ על הלחצן Continue, הדפדפן פותח חלון קופץ לדף ההתחברות של ה-IdP.

An
תיבת דו-שיח לדוגמה שמוצגת אחרי שלוחצים על לחצן הכניסה ללחצן IdP.

תיבת הדו-שיח היא חלון דפדפן רגיל עם קובצי cookie מהדומיין הנוכחי. מה שיקרה בתיבת הדו-שיח תלוי ב-IdP, ולא יהיו כינויים של חלונות כדי לשלוח בקשת תקשורת ממקורות שונים לדף ה-RP. אחרי שהמשתמש נכנס, ה-IdP צריך:

  • צריך לשלוח את הכותרת Set-Login: logged-in או לקרוא ל- navigator.login.setStatus("logged-in") API כדי להודיע לדפדפן שהמשתמש נכנס.
  • צריך להתקשר אל IdentityProvider.close() כדי לסגור את תיבת הדו-שיח.
A
משתמש נכנס ל-RP אחרי שהוא נכנס ל-IdP באמצעות FedCM.

הודעה לדפדפן לגבי סטטוס ההתחברות של המשתמש בספק הזהויות

Login Status API הוא מנגנון שבו אתר, במיוחד IdP, מודיע לדפדפן את סטטוס ההתחברות של המשתמש ב-IdP. בעזרת ה-API הזה, הדפדפן יכול לצמצם בקשות מיותרות ל-IdP ולצמצם התקפות תזמון פוטנציאליות.

ספקי IdP יכולים לאותת את סטטוס ההתחברות של המשתמשים לדפדפן על ידי שליחת כותרת HTTP או על ידי קריאה ל-JavaScript API כשהמשתמש מחובר ל-IdP או כשהמשתמש יוצא מכל חשבונות ה-IdP שלהם. לכל IdP (שמזוהה באמצעות כתובת ה-URL להגדרה שלו), הדפדפן שומר משתנה תלת-מצבי שמייצג את מצב ההתחברות עם הערכים האפשריים logged-in, logged-out ו-unknown. מצב ברירת המחדל הוא unknown.

כדי לסמן שהמשתמש מחובר, צריך לשלוח כותרת HTTP מסוג Set-Login: logged-in בניווט ברמה העליונה או בבקשה למשאב משנה באותו אתר במקור של ה-IdP:

Set-Login: logged-in

לחלופין, קוראים ל-JavaScript API navigator.login.setStatus("logged-in") מהמקור של ה-IdP בניווט ברמה העליונה:

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

בשיחות האלה אפשר לראות את סטטוס ההתחברות של המשתמש בתור logged-in. כשסטטוס ההתחברות של המשתמש מוגדר כ-logged-in, הגורם המוגבל שקורא ל-FedCM שולח בקשות לנקודת הקצה של חשבונות ה-IdP ומציג חשבונות זמינים למשתמש בתיבת הדו-שיח של FedCM.

כדי לסמן שהמשתמש יוצא מכל החשבונות, צריך לשלוח את כותרת ה-HTTP Set-Login: logged-out בניווט ברמה העליונה או בבקשת משאב משנה באותו אתר במקור ה-IdP:

Set-Login: logged-out

לחלופין, קוראים ל-JavaScript API navigator.login.setStatus("logged-out") מהמקור של ה-IdP בניווט ברמה העליונה:

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

בשיחות האלה אפשר לראות את סטטוס ההתחברות של המשתמש בתור logged-out. כשסטטוס ההתחברות של המשתמש הוא logged-out, קריאה ל-FedCM נכשלת בלי לשלוח בקשה לנקודת הקצה של חשבונות ה-IdP.

הסטטוס unknown מוגדר לפני שה-IdP שולח אות באמצעות ה-API של סטטוס ההתחברות. הוספנו את Unknown כדי לאפשר מעבר טוב יותר, כי יכול להיות שמשתמש כבר היה נכנס ל-IdP כשה-API הזה נשלח. ייתכן ש-IdP לא יוכל לאותת זאת לדפדפן עד להפעלה הראשונה של FedCM. במקרה כזה, Chrome שולח בקשה לנקודת הקצה של חשבונות ה-IdP ומעדכן את הסטטוס בהתאם לתגובה מנקודת הקצה של החשבונות:

  • אם נקודת הקצה מחזירה רשימה של חשבונות פעילים, מעדכנים את הסטטוס ל-logged-in ופותחים את תיבת הדו-שיח של FedCM כדי להציג את החשבונות האלה.
  • אם נקודת הקצה לא מחזירה חשבונות, מעדכנים את הסטטוס ל-logged-out והפעולה של FedCM נכשלת.

אפשר למשתמש להיכנס באמצעות זרימת התחברות דינמית

על אף שה-IdP כל הזמן מודיע על סטטוס ההתחברות של המשתמש לדפדפן, יכול להיות שהוא לא יהיה מסונכרן, למשל מתי יפוג תוקף הסשן. הדפדפן מנסה לשלוח בקשה עם פרטי כניסה לנקודת הקצה של החשבונות כשסטטוס ההתחברות הוא logged-in, אבל השרת לא מחזיר חשבונות כי הסשן לא זמין יותר. בתרחיש כזה, הדפדפן יכול לאפשר למשתמש באופן דינמי להיכנס ל-IdP דרך חלון קופץ.

כניסה לצד הנסמך באמצעות ספק הזהויות

כשההגדרות ונקודות הקצה של ה-IdP יהיו זמינות, הגורמים המוגבלים יכולים לבצע קריאה ל-navigator.credentials.get() כדי לבקש ממשתמשים להיכנס ל-RP באמצעות ה-IdP.

לפני שמפעילים את ה-API, חשוב לוודא ש-[FedCM זמין בדפדפן של המשתמש]. כדי לבדוק אם FedCM זמין, יש לעטוף את הקוד הזה בהטמעת FedCM:

if ('IdentityCredential' in window) {
  // If the feature is available, take action
}

כדי לבקש שהמשתמשים יוכלו להיכנס ל-IdP מה-RP, צריך לבצע את הפעולות הבאות:

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

המאפיין providers מקבל מערך של IdentityProvider אובייקטים בעלי המאפיינים הבאים:

מאפיין (property) תיאור
configURL (חובה) נתיב מלא של קובץ התצורה של IdP.
clientId (חובה) מזהה הלקוח של הגורם המוגבל, שהונפק על ידי ה-IdP.
ֶnonce (אופציונלי) מחרוזת אקראית שמטרתה לוודא שהתגובה תונפק לבקשה הספציפית הזו. מניעת התקפות שליחה מחדש
ֶloginHint (אופציונלי) כשמציינים אחד מהערכים של login_hints שסופקו על ידי נקודות הקצה של החשבונות, החשבון שצוין בתיבת הדו-שיח של FedCM יוצג באופן סלקטיבי.
ֶdomainHint (אופציונלי) כשמציינים אחד מהערכים של domain_hints שסופקו על ידי נקודות הקצה של החשבונות, החשבון שצוין בתיבת הדו-שיח של FedCM יוצג באופן סלקטיבי.

הדפדפן מטפל בתרחישים לדוגמה של הרשמה וכניסה באופן שונה, בהתאם לקיום של approved_clients בתגובה מנקודת הקצה של רשימת החשבונות. אם המשתמש כבר נרשם ל-RP, הדפדפן לא יציג את הטקסט 'להמשך עם ....' של הגילוי הנאות.

מצב ההרשמה נקבע אם התנאים הבאים מתקיימים או לא:

  • אם approved_clients כולל את clientId של הגורם המוגבל.
  • אם הדפדפן זוכר שהמשתמש כבר נרשם לגורם מוגבל.
משתמש נכנס ל-RP באמצעות FedCM

כשה-RP קורא ל-navigator.credentials.get(), מתרחשות הפעילויות הבאות:

  1. הדפדפן שולח בקשות ומאחזר כמה מסמכים:
    1. הקובץ המוכר וקובץ התצורה IdP שמצהירים בו על נקודות הקצה.
    2. רשימת חשבונות.
    3. אופציונלי: כתובות URL של מדיניות הפרטיות והתנאים וההגבלות של ה-RP, שמאחזרות מנקודת הקצה של המטא-נתונים של הלקוח.
  2. בדפדפן תוצג רשימת החשבונות שבאמצעותם המשתמש יכול להיכנס, וגם את התנאים וההגבלות ואת מדיניות הפרטיות, אם יש כאלה.
  3. אחרי שהמשתמש בוחר חשבון להיכנס באמצעותו, בקשה לנקודת הקצה של טענת הנכוֹנוּת (assertion) נשלחת ל-IdP כדי לאחזר אסימון.
  4. ה-RP יכול לאמת את האסימון כדי לאמת את המשתמש.
קריאה ל-API להתחברות
קריאה ל-API להתחברות

גורמים מוגבלים צפויים לתמוך בדפדפנים שלא תומכים ב-FedCM, ולכן צריכה להיות להם אפשרות להשתמש בתהליך כניסה קיים שלא של FedCM. עד שקובצי cookie של צד שלישי יוצאו משימוש לחלוטין, מצב זה אמור להישאר לא בעייתי.

אחרי ששרת ה-RP מאמת את האסימון, ה-RP עשוי לרשום את המשתמש או לאפשר לו להיכנס ולהתחיל סשן חדש.

ממשק API של רמז להתחברות

אחרי שהמשתמש נכנס, לפעמים הצד הנסמך (RP) מבקש מהמשתמש לבצע אימות מחדש. עם זאת, ייתכן שהמשתמש לא בטוח באיזה חשבון הוא השתמש. אם ה-RP יכול לציין עם איזה חשבון להיכנס, יהיה למשתמש קל יותר לבחור חשבון.

גורמים מוגבלים יכולים להציג חשבון ספציפי באופן סלקטיבי על ידי הפעלה של navigator.credentials.get() עם הנכס loginHint עם אחד מהערכים של login_hints שמאוחזר מנקודת הקצה של רשימת החשבונות, כפי שמוצג בדוגמת הקוד הבאה:

return await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: "https://idp.example/manifest.json",
      clientId: "123",
      nonce: nonce,
      loginHint : "demo1@example.com"
    }]
  }
});

כשאין חשבונות שתואמים ל-loginHint, בתיבת הדו-שיח של FedCM מוצגת בקשה להתחברות שמאפשרת למשתמש להתחבר לחשבון IdP שתואם לרמז המבוקש על ידי ה-RP. כשהמשתמש מקיש על הבקשה, נפתח חלון קופץ עם כתובת ה-URL להתחברות שצוינה בקובץ התצורה. לאחר מכן הקישור מצרף את הרמז להתחברות והפרמטרים של השאילתה עם הרמז לדומיין.

ממשק API של Domain Hint

יש מקרים שבהם הגורם המוגבל כבר יודע שרק חשבונות שמשויכים לדומיין מסוים מורשים להתחבר לאתר. זה נכון במיוחד בתרחישים ארגוניים שבהם הגישה לאתר מוגבלת לדומיין ארגוני. כדי לספק חוויית משתמש טובה יותר, ה-API של FedCM מאפשר ל-RP להציג רק את החשבונות שניתן להשתמש בהם כדי להתחבר ל-RP. האפשרות הזו מונעת תרחישים שבהם משתמש מנסה להתחבר ל-RP באמצעות חשבון מחוץ לדומיין התאגידי, אבל תוצג הודעת שגיאה מאוחר יותר (או השתקה במקום שבו ההתחברות לא עבדה), מכיוון שלא נעשה שימוש בסוג החשבון הנכון.

גורמים מוגבלים יכולים להציג באופן סלקטיבי רק חשבונות תואמים על ידי הפעלה של navigator.credentials.get() עם הנכס domainHint עם אחד מהערכים של domain_hints שמאוחזר מנקודת הקצה של רשימת החשבונות, כפי שמוצג בדוגמת הקוד הבאה:

return await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: "https://idp.example/manifest.json",
      clientId: "abc",
      nonce: nonce,
      domainHint : "corp.example"
    }]
  }
});

כשאין חשבונות שתואמים ל-domainHint, בתיבת הדו-שיח של FedCM מוצגת בקשה להתחברות שמאפשרת למשתמש להתחבר לחשבון IdP שתואם לרמז המבוקש על ידי ה-RP. כשהמשתמש מקיש על הבקשה, נפתח חלון קופץ עם כתובת ה-URL להתחברות שצוינה בקובץ התצורה. לאחר מכן הקישור מצרף את הרמז להתחברות והפרמטרים של השאילתה עם הרמז לדומיין.

דוגמה לבקשת התחברות כשאין חשבונות שתואמים ל-domainHint.
דוגמה לבקשת התחברות כשאין חשבונות שתואמים לdomainHint.

הצגת הודעת שגיאה

לפעמים ה-IdP לא יוכל להנפיק אסימון מסיבות לגיטימיות, למשל כשהלקוח לא מורשה, השרת לא זמין באופן זמני. אם ה-IdP מחזיר תגובה מסוג 'שגיאה', ה-RP יכול לאתר אותה, וגם Chrome שולח הודעה למשתמש באמצעות הצגת ממשק משתמש של הדפדפן עם פרטי השגיאה שסופקו על ידי ה-IdP.

A
תיבת דו-שיח של FedCM שמוצגת בה הודעת השגיאה אחרי שניסיון הכניסה של המשתמש נכשל. המחרוזת משויכת לסוג השגיאה.
try {
  const cred = await navigator.credentials.get({
    identity: {
      providers: [
        {
          configURL: "https://idp.example/manifest.json",
          clientId: "1234",
        },
      ],
    }
  });
} catch (e) {
  const code = e.code;
  const url = e.url;
}

אימות אוטומטי מחדש של משתמשים לאחר ההסכמה הראשונית

אימות מחדש אוטומטי של FedCM (בקיצור: "auto-reauthn") יכול לאפשר למשתמשים לבצע אימות מחדש באופן אוטומטי כשהם חוזרים אחרי האימות הראשוני באמצעות FedCM. המשמעות של 'האימות הראשוני' כאן הוא שהמשתמש יוצר חשבון או נכנס לאתר של הגורם המוגבל על ידי הקשה על הלחצן 'המשך בתור...' בתיבת הדו-שיח לכניסה של FedCM בפעם הראשונה, באותו מופע של הדפדפן.

יש היגיון בחוויית המשתמש המפורשת לפני שהמשתמש יצר חשבון מאוחד כדי למנוע מעקב (שהוא אחד מהיעדים העיקריים של FedCM), אבל הוא מורכב שלא לצורך אחרי שהמשתמש עבר אותו פעם אחת: אחרי שהמשתמש מעניק הרשאה לאפשר תקשורת בין ה-RP ל-IdP, אין שום יתרון של פרטיות או אבטחה אם הוא אוכף מידע מפורש של משתמש אחר.

באימות מחדש אוטומטי, הדפדפן משנה את ההתנהגות שלו בהתאם לאפשרות שציינתם ל-mediation בקריאה ל-navigator.credentials.get().

const cred = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: "https://idp.example/fedcm.json",
      clientId: "1234",
    }],
  },
  mediation: 'optional', // this is the default
});

// `isAutoSelected` is `true` if auto-reauthn was performed.
const isAutoSelected = cred.isAutoSelected;

mediation הוא מאפיין ב-API לניהול פרטי הכניסה, הוא מתנהג באותו אופן כמו שהוא מתנהג עבור PasswordCredential ו-FederatedCredential, וגם הוא נתמך חלקית על ידי PublicKeyCredential. הנכס מקבל את ארבעת הערכים הבאים:

  • 'optional'(ברירת מחדל): אימות מחדש אוטומטי אם ניתן, מחייב גישור אם לא. מומלץ לבחור באפשרות הזו בדף הכניסה.
  • 'required': נדרש גישור כדי להמשיך, לדוגמה, לחיצה על הלחצן 'המשך' בממשק המשתמש. בחרו באפשרות הזו אם המשתמשים שלכם נדרשים להעניק הרשאה באופן מפורש בכל פעם שהם צריכים לעבור אימות.
  • 'silent': אימות מחדש אוטומטי אם אפשר, נכשל ברקע ללא צורך בגישור אם לא. מומלץ לבחור באפשרות זו בדפים אחרים מלבד דף הכניסה הייעודי, שבו רוצים להשאיר את המשתמשים מחוברים - לדוגמה, דף פריט באתר משלוחים או דף מאמר באתר חדשות.
  • 'conditional': משמש ל-WebAuthn ולא זמין ל-FedCM כרגע.

בשיחה הזו, האימות מחדש יתבצע בתנאים הבאים:

  • FedCM זמין לשימוש. לדוגמה, המשתמש לא השבית את FedCM באופן גלובלי או עבור ה-RP בהגדרות.
  • המשתמש השתמש רק בחשבון אחד ב-FedCM API כדי להיכנס לאתר בדפדפן הזה.
  • המשתמש נכנס ל-IdP עם החשבון הזה.
  • האימות מחדש לא בוצע ב-10 הדקות האחרונות.
  • הגורם המוגבל לא קרא ל-navigator.credentials.preventSilentAccess() אחרי הכניסה הקודמת.

כשהתנאים האלה מתקיימים, ניסיון אימות מחדש של המשתמש יתחיל באופן אוטומטי מיד עם הפעלת navigator.credentials.get() של FedCM.

כאשר mediation: optional, auto-reauthn עשוי להיות לא זמין בגלל סיבות שרק הדפדפן יודע. ה-RP יכול לבדוק אם הוא מבוצע על ידי בדיקת המאפיין isAutoSelected.

המידע הזה עוזר להעריך את ביצועי ה-API ולשפר את חוויית המשתמש בהתאם. בנוסף, כשהיא לא זמינה, יכול להיות שהמשתמש יתבקש להיכנס באמצעות תהליך בחירת הרשת (Mediation) מפורש, שהוא תהליך עם mediation: required.

משתמש שמבצע אימות מחדש באופן אוטומטי באמצעות FedCM.

אכיפה של תהליך בחירת הרשת (Mediation) עם preventSilentAccess()

אימות אוטומטי מחדש של המשתמשים מיד אחרי שהם יוצאים מהחשבון לא יוצר חוויית משתמש טובה מאוד. לכן, ב-FedCM יש פרק זמן שקט של 10 דקות אחרי האימות האוטומטי, כדי למנוע התנהגות כזו. כלומר, אימות אוטומטי מתבצע לכל היותר פעם ב-10 דקות, אלא אם המשתמש נכנס שוב תוך 10 דקות. ה-RP צריך להפעיל את navigator.credentials.preventSilentAccess() כדי לבקש באופן מפורש מהדפדפן להשבית את האימות האוטומטי כשהמשתמש יוצא מה-RP באופן מפורש, לדוגמה, על ידי לחיצה על לחצן יציאה.

function signout() {
  navigator.credentials.preventSilentAccess();
  location.href = '/signout';
}

המשתמשים יכולים לבטל את ההסכמה לאימות מחדש אוטומטי בהגדרות

המשתמשים יכולים לבטל את ההסכמה לאימות מחדש אוטומטי מתפריט ההגדרות:

  • ב-Chrome במחשב, עוברים אל chrome://password-manager/settings > כניסה אוטומטית.
  • ב-Android Chrome, פותחים את הגדרות > מנהל הסיסמאות > מקישים על גלגל השיניים בפינה השמאלית העליונה > כניסה אוטומטית.

השבתת המתג מאפשרת למשתמש לבטל לגמרי את ההסכמה להתנהגות של אימות מחדש אוטומטי. ההגדרה הזו מאוחסנת ומסונכרנת בין מכשירים אם המשתמש נכנס לחשבון Google במופע של Chrome והסנכרון מופעל.

ניתוק ה-IdP מה-RP

אם משתמש נכנס בעבר ל-RP באמצעות ה-IdP דרך FedCM, הקשר יישמר בעל-פה באופן מקומי בדפדפן כרשימת החשבונות המקושרים. הגורם המוגבל יכול ליזום ניתוק על ידי הפעלת הפונקציה IdentityCredential.disconnect(). אפשר לקרוא לפונקציה הזו ממסגרת של גורם מוגבל (RP) ברמה העליונה. ה-RP צריך להעביר configURL, clientId שנעשה בו שימוש ב-IdP ו-accountHint כדי שה-IdP ינותק. רמז לחשבון יכול להיות מחרוזת שרירותית כל עוד נקודת הקצה לניתוק יכולה לזהות את החשבון, לדוגמה, כתובת אימייל או מזהה משתמש שלא תואמים בהכרח למספר החשבון שסופק על ידי נקודת הקצה של רשימת החשבונות:

// Disconnect an IdP account "account456" from the RP "https://idp.com/". This is invoked on the RP domain.
IdentityCredential.disconnect({
  configURL: "https://idp.com/config.json",
  clientId: "rp123",
  accountHint: "account456"
});

הפונקציה IdentityCredential.disconnect() מחזירה Promise. ההבטחה הזו עשויה לגרום לחריגה מהסיבות הבאות:

  • המשתמש לא נכנס ל-RP באמצעות ה-IdP דרך FedCM.
  • ה-API מופעל מתוך iframe ללא מדיניות ההרשאות של FedCM.
  • ה-configURL לא חוקי או חסרה נקודת הקצה לניתוק.
  • הבדיקה של Content Security Policy (CSP) נכשלה.
  • יש בקשת ניתוק בהמתנה.
  • המשתמש השבית את FedCM בהגדרות הדפדפן.

כשמנקודת הקצה הניתוק של ה-IdP מחזירה תשובה, ה-RP וה-IdP מנותקים בדפדפן וההבטחה נפתרה. המזהה של החשבונות המנותקים מצוין בתגובה לנקודת הקצה הניתוק.

קריאה ל-FedCM מתוך iframe חוצה-מקורות

אפשר להפעיל את FedCM מתוך iframe ממקורות שונים באמצעות מדיניות ההרשאות identity-credentials-get, אם מסגרת ההורה מאפשרת זאת. כדי לעשות זאת, מוסיפים את המאפיין allow="identity-credentials-get" לתג ה-iframe באופן הבא:

<iframe src="https://fedcm-cross-origin-iframe.glitch.me" allow="identity-credentials-get"></iframe>

אפשר לראות זאת בפעולה בדוגמה.

לחלופין, אם מסגרת ההורה רוצה להגביל את המקורות לקריאה ל-FedCM, צריך לשלוח כותרת Permissions-Policy עם רשימה של מקורות מורשים.

Permissions-Policy: identity-credentials-get=(self "https://fedcm-cross-origin-iframe.glitch.me")

במאמר שליטה בתכונות הדפדפן באמצעות מדיניות הרשאות מוסבר איך המדיניות בנושא הרשאות פועלת.