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

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

ניהול פרטי כניסה מאוחדים (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/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 על ידי RPs. מספר מחרוזות כתובות ה-URL במערך מוגבל לאחת, אבל זה עשוי להשתנות בהתאם למשוב שלכם בעתיד.

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

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

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

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

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

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

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

נכס תיאור
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 לנקודת הקצה הזו של הניתוק עם המידע הבא:

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

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

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

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

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

כשהמשתמש לוחץ על הלחצן Continue, הדפדפן פותח חלון קופץ לדף ההתחברות של ה-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 בתשובה מנקודת הקצה של רשימת החשבונות. אם המשתמש כבר נרשם ל-RP, לא יוצג בדפדפן הטקסט של גילוי הנאות "To continue with ....".

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

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

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

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

יש מקרים שבהם הגורם המוגבל כבר יודע שרק לחשבונות שמשויכים לדומיין מסוים יכולים להתחבר לאתר. המצב הזה נפוץ במיוחד בתרחישים ארגוניים שבהם הגישה לאתר מוגבלת לדומיין ארגוני. כדי לספק חוויית משתמש טובה יותר, FedCM API מאפשר ל-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. 'אימות ראשוני' כאן פירושו שהמשתמש יוצר חשבון או נכנס לאתר של 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': תמיד צריך להגדיר תהליך בחירת רשת כדי להמשיך, לדוגמה, לחיצה על הלחצן Continue (המשך) בממשק המשתמש. בוחרים באפשרות הזו אם המשתמשים אמורים להעניק הרשאה במפורש בכל פעם שהם צריכים לבצע אימות.
  • '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 > כניסה אוטומטית.
  • ב-Android Chrome, פותחים את הגדרות > מנהל הסיסמאות > מקישים על סמל גלגל השיניים בפינה השמאלית העליונה > כניסה אוטומטית.

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

קריאה ל-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")

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