המדריך למפתחים של Federated Credential Management API

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

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

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

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

כדי להשתמש ב-FedCM, צריך הקשר מאובטח (HTTPS או localhost) גם ב-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, יוצרים קובץ ידוע, קובץ תצורה ונקודות קצה לרשימת החשבונות, להנפקת טענות נכוֹנוּת ולמטא-נתונים של הלקוח (אופציונלי).

משם, FedCM חושף ממשקי API של JavaScript שבהם ספקי ה-RP יכולים להשתמש כדי להיכנס לחשבון ב-IdP.

יצירת קובץ well-known

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

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

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

קובץ ה-JSON חייב להכיל את המאפיין provider_urls עם מערך של כתובות URL של קובץ תצורה של IdP, שאפשר לציין כחלק מנתיב של configURL ב-navigator.credentials.get על ידי RPs. מספר מחרוזות כתובות ה-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, שכוללת את המאפיינים הבאים:

נכס תיאור
accounts_endpoint (חובה) כתובת ה-URL של נקודת הקצה (endpoint) של החשבונות.
ֶclient_metadata_endpoint (אופציונלי) כתובת ה-URL של נקודת הקצה של מטא-נתוני הלקוח.
id_assertion_endpoint (חובה) כתובת ה-URL של נקודת הקצה לאימות הזהות.
ֶ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 עם מערך של פרטי החשבון עם המאפיינים הבאים:

נכס תיאור
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 מראש קישורים למדיניות הפרטיות ולתנאים ולהגבלות שלהם. הקישורים האלה מוצגים בתיבת הדו-שיח של הכניסה כשהמשתמש עדיין לא נרשם ב-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. משיבים עם המטא-נתונים של הלקוח.

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

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

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

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

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

נקודת קצה לאישור זהות

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

נכס תיאור
client_id (חובה) מזהה הלקוח של RP.
account_id (חובה) המזהה הייחודי של המשתמש שנכנס לחשבון.
ֶnonce (אופציונלי) המזהה החד-פעמי של הבקשה, שסופק על ידי ה-RP.
disclosure_text_shown הפונקציה מחזירה מחרוזת של "true" או "false" (במקום ערך בוליאני). התוצאה היא "false" אם טקסט הגילוי הנאות לא הוצג. המצב הזה מתרחש כאשר מזהה הלקוח של RP נכלל ברשימת המאפיינים approved_clients בתגובה מנקודת הקצה accounts, או אם הדפדפן זיהה רגע הרשמה בעבר ללא 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 שכוללת את המאפיין הבא:

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

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

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

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

  • 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 לנקודת הקצה הזו לניתוק, עם הפרטים הבאים:

נכס תיאור
account_hint רמז לחשבון ה-IdP.
client_id מזהה הלקוח של RP.
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.

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

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

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

  • שולחים את הכותרת Set-Login: logged-in או קוראים ל-API‏ navigator.login.setStatus("logged-in") כדי להודיע לדפדפן שהמשתמש נכנס לחשבון.
  • מקישים על IdentityProvider.close() כדי לסגור את תיבת הדו-שיח.
משתמש נכנס לחשבון ב-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, ה-RP שמפעיל את 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 יהיו זמינות, ספקי ה-RP יוכלו לבצע קריאה ל-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 שיש להם את המאפיינים הבאים:

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

הדפדפן מטפל בתרחישי השימוש של הרשמה וכניסה באופן שונה, בהתאם לנוכחות של approved_clients בתגובה מנקודת הקצה של רשימת החשבונות. הדפדפן לא יציג את הטקסט של גילוי הנאות "To continue with ...." אם המשתמש כבר נרשם ל-RP.

סטטוס ההרשמה נקבע על סמך התנאים הבאים:

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

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

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

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

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

Login Hint 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 להתחברות שצוינה בקובץ התצורה. לאחר מכן, הקישור יתווספו לו פרמטרים של שאילתות של רמז להתחברות ורמז לדומיין.

Domain Hint API

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

כדי להציג באופן סלקטיבי רק חשבונות תואמים, שותפי ה-API יכולים להפעיל את 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 (בקיצור 'אימות מחדש אוטומטי') מאפשר למשתמשים לבצע אימות מחדש באופן אוטומטי כשהם חוזרים אחרי האימות הראשוני באמצעות FedCM. 'אימות ראשוני' כאן פירושו שהמשתמש יוצר חשבון או נכנס לאתר של RP על ידי הקשה על הלחצן 'המשך בתור…' בתיבת הדו-שיח של 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 הוא מאפיין ב-Credential Management API, והוא פועל באותו אופן כמו ב-PasswordCredential וב-FederatedCredential, ויש לו תמיכה חלקית גם ב-PublicKeyCredential. המאפיין יכול לקבל את ארבעת הערכים הבאים:

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

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

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

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

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

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

משתמש שמבצע אימות חוזר אוטומטי דרך FedCM.

אכיפת תהליך בחירת הרשת באמצעות preventSilentAccess()

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

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

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

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

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

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

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

אם משתמש נכנס בעבר ל-RP באמצעות ה-IdP דרך FedCM, הדפדפן שומר את הקשר באופן מקומי כרשימה של החשבונות המקושרים. ה-RP יכול ליזום ניתוק על ידי הפעלת הפונקציה 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")

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