הטמעת פתרון זהויות באמצעות FedCM בצד של ספק הזהויות

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

IdPs צריכים לבצע את השלבים הבאים כדי להטמיע את FedCM:

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

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

הקובץ המוכר יכול לכלול את המאפיינים הבאים:

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

הערה: הפרמטר נתמך החל מ-Chrome 132.
login_url מומלץ, נדרש מינוי ל-accounts_endpoint כתובת ה-URL של דף הכניסה שדרכו המשתמש נכנס ל-IdP. האפשרות הזו מאפשרת תמיכה בכמה הגדרות, כל עוד כל קובץ הגדרות משתמש באותם login_url וaccounts_endpoint.

הערה: הפרמטר נתמך החל מ-Chrome 132 ואילך.

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

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

ספקי זהויות יכולים להכיל כמה קובצי הגדרות לספק זהויות, על ידי ציון accounts_endpoint ו-login_url בקובץ well-known. התכונה הזו יכולה להיות שימושית במקרים הבאים:

  • ספק זהויות צריך לתמוך בכמה תצורות שונות של בדיקות ושל ייצור.
  • ספק הזהויות צריך לתמוך בהגדרות שונות לכל אזור (לדוגמה, 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"
  }

יצירת קובץ תצורה ונקודות קצה של ספק זהויות

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

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

  // 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. לבקשה אין קובצי Cookie והיא לא עוקבת אחרי הפניות אוטומטיות. בפועל, זה מונע מספק הזהויות לדעת מי שלח את הבקשה ואיזה RP מנסה להתחבר. לדוגמה:

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

ספק הזהויות צריך להטמיע נקודת קצה של הגדרות שמגיבה עם JSON. קובץ ה-JSON כולל את המאפיינים הבאים:

נכס תיאור
accounts_endpoint (חובה) כתובת ה-URL של נקודת הקצה של החשבונות.
ֶaccount_label (אופציונלי) מחרוזת של תווית חשבון בהתאמה אישית, שקובעת אילו חשבונות יוחזרו כשמשתמשים בקובץ ההגדרות הזה, לדוגמה: "account_label": "developer".
ספק IdP יכול להטמיע תיוג חשבונות בהתאמה אישית באופן הבא:

לדוגמה, ספק הזהויות מטמיע "https://idp.example/developer-config.json" קובץ הגדרות עם "account_label": "developer" שצוין. ספק ה-IdP מסמן גם חלק מהחשבונות בתווית "developer" באמצעות הפרמטר label_hints בנקודת הקצה של החשבונות. כשספק זהויות קורא ל-navigator.credentials.get() עם קובץ ההגדרות "https://idp.example/developer-config.json" שצוין, רק חשבונות עם התווית "developer" יוחזרו.

הערה: תוויות חשבון בהתאמה אישית נתמכות החל מ-Chrome 132.
ֶsupports_use_other_account (אופציונלי) ערך בוליאני שמציין אם המשתמש יכול להיכנס באמצעות חשבון ששונה מהחשבון שאיתו הוא מחובר כרגע (אם ספק הזהויות תומך בכמה חשבונות). ההגדרה הזו רלוונטית רק למצב פעיל.
ֶ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 (אופציונלי): מידות הסמל, שהאפליקציה מניחה שהוא ריבועי ובעל רזולוציה אחת. במצב פסיבי, המספר הזה צריך להיות 25px או יותר, ובמצב פעיל הוא צריך להיות 40px או יותר.

זוהי דוגמה לגוף התגובה מ-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
נקודות קצה של ספק הזהויות

שימוש בחשבון אחר

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

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

  {
    "accounts_endpoint" : "/accounts.example",
    "supports_use_other_account": true
  }

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

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

הדפדפן שולח בקשת GET עם קובצי Cookie עם 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

כשהשרת מקבל את הבקשה, הוא צריך:

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

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

נכס תיאור
id (חובה) מזהה ייחודי של המשתמש.
name השם המלא של המשתמש בהתאם ללוקאל ולהעדפות שלו.

הערה: החל מ-Chrome 141, נדרש לפחות אחד מהפרמטרים name,‏ email,‏ username או tel. בגרסאות קודמות של Chrome, נדרשים גם name וגם email.
username שם משתמש שנבחר על ידי המשתמש.

הערה: החל מ-Chrome 141, נדרש לפחות אחד מהפרמטרים name,‏ email,‏ username או tel.
email כתובת האימייל של המשתמש.

הערה: החל מ-Chrome 141, נדרש לפחות אחד מהפרמטרים name,‏ email,‏ username או tel. בגרסאות קודמות של Chrome, נדרשים גם name וגם email.
tel מספר הטלפון של המשתמש.

הערה: החל מ-Chrome 141, נדרש לפחות אחד מהפרמטרים name,‏ email,‏ username או tel.
ֶpicture (אופציונלי) כתובת ה-URL של תמונת הדמות של המשתמש.
ֶgiven_name (אופציונלי) השם הפרטי של המשתמש.
ֶapproved_clients (אופציונלי) מערך של מספרי לקוח של ספקי זהויות שהמשתמש נרשם אליהם.
ֶlogin_hints (אופציונלי) מערך של כל סוגי המסננים האפשריים שספק הזהויות תומך בהם כדי לציין חשבון. ספק ה-RP יכול להפעיל את navigator.credentials.get() עם המאפיין loginHint כדי להציג באופן סלקטיבי את החשבון שצוין.
ֶdomain_hints (אופציונלי) מערך של כל הדומיינים שהחשבון משויך אליהם. ספק הזהויות יכול להתקשר אל navigator.credentials.get() עם מאפיין domainHint כדי לסנן את החשבונות.
ֶlabel_hints (אופציונלי) מערך של תוויות חשבון מותאמות אישית מסוג מחרוזת שחשבון משויך אליהן.
ספק IdP יכול להטמיע תיוג חשבונות בהתאמה אישית באופן הבא:
  • מציינים תוויות של חשבונות בנקודת הקצה של החשבונות (באמצעות הפרמטר label_hints).
  • יוצרים קובץ הגדרות לכל תווית ספציפית.

לדוגמה, ספק הזהויות מטמיע https://idp.example/developer-config.json קובץ הגדרה עם "account_label": "developer" שצוין. ספק ה-IdP מסמן גם חלק מהחשבונות בתווית "developer" באמצעות הפרמטר label_hints ב נקודת הקצה של החשבונות. כש-RP קורא ל-navigator.credentials.get() עם קובץ הגדרות https://idp.example/developer-config.json שצוין, רק חשבונות עם התווית "developer" יוחזרו.

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

הערה: תוויות חשבון בהתאמה אישית נתמכות החל מ-Chrome 132.

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

  {
    "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 באמצעות קריאה ל-navigator.credentials.get(), הדפדפן שולח בקשת POST עם קובצי Cookie עם SameSite=None וסוג תוכן של application/x-www-form-urlencoded לנקודת הקצה הזו עם הפרטים הבאים:

נכס תיאור
client_id (חובה) מזהה הלקוח של ספק הזהויות.
account_id (חובה) המזהה הייחודי של המשתמש שנכנס לחשבון.
disclosure_text_shown הפונקציה מחזירה מחרוזת של "true" או "false" (ולא ערך בוליאני). התוצאה היא "false" במקרים הבאים:
  • אם טקסט הגילוי הנאות לא הוצג כי מזהה הלקוח של ספק שירותי ה-RP נכלל ברשימת המאפיינים approved_clients של התגובה מנקודת הקצה של החשבונות.
  • אם טקסט הגילוי הנאות לא הוצג כי הדפדפן זיהה בעבר רגע הרשמה בהיעדר approved_clients.
  • אם הפרמטר fields לא כולל את כל שלושת השדות (name,‏ email ו-picture), לדוגמה, fields=[ ] או fields=['name', 'picture']. ההרשאה הזו נדרשת לתאימות לאחור עם הטמעות ישנות יותר.

    הערה: החל מגרסה Chrome 141, יכול להיות שטקסט הגילוי הנאות יוצג גם אם הערך של disclosure_text_shown הוא "false". כדי לבדוק אם טקסט הגילוי הנאות הוצג, בודקים את הערך disclosure_shown_for.
disclosure_shown_for רשימה של השדות שהדפדפן הציג למשתמש בטקסט הגילוי הנאות, כדי להודיע למשתמש אילו נתונים ספק ה-RP מבקש מספק ה-IdP.
is_auto_selected אם מתבצע אימות מחדש אוטומטי ב-RP, הערך is_auto_selected מציין "true". אחרת "false". המידע הזה עוזר לנו לתמוך בתכונות נוספות שקשורות לאבטחה. לדוגמה, יכול להיות שחלק מהמשתמשים יעדיפו רמת אבטחה גבוהה יותר, שדורשת תיווך מפורש של המשתמש באימות. אם ספק זהויות מקבל בקשה לאסימון ללא תיווך כזה, הוא עשוי לטפל בבקשה בצורה שונה. לדוגמה, להחזיר קוד שגיאה כך שספק הזהויות יוכל לקרוא שוב ל-FedCM API עם mediation: required.
ֶfields (אופציונלי) מערך של מחרוזות שמציין את פרטי המשתמש שספק ה-RP ביקש מספק ה-IdP לשתף. אפשר לציין את השדות הבאים:
  • "name"
  • "username"
  • "email"
  • "tel"
  • "picture"
הדפדפן ישלח את fields,‏ disclosure_text_shown ו-disclosure_shown_for עם רשימה של השדות שצוינו בבקשת ה-POST, כמו בדוגמה הבאה.

הערה: Fields API נתמך ב-Chrome 132 ואילך. השדות ‎ `"username"` ‎ ו-‎ `"tel"` ‎ נתמכים החל מ-Chrome 141.
ֶparams (אופציונלי) כל אובייקט JSON תקין שמאפשר לציין פרמטרים נוספים מותאמים אישית של מפתח/ערך, לדוגמה:
  • scope: ערך מחרוזת שמכיל הרשאות נוספות שספק הזהויות צריך לבקש, לדוגמה "drive.readonly calendar.readonly"
  • nonce: מחרוזת אקראית שספק הזהויות מספק כדי לוודא שהתשובה מונפקת לבקשה הספציפית הזו. מונעת התקפות חוזרות.
  • פרמטרים מותאמים אישית אחרים של מפתח/ערך.
כשהדפדפן שולח בקשת POST, הערך של params עובר סריאליזציה ל-JSON ואז קידוד באחוזים.

הערה: API של פרמטרים נתמך ב-Chrome מגרסה 132 ואילך.

כותרת 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&params=%22%7B%5C%22nonce%5C%22%3A%5C%22nonce-value%5C%22%7D%22.%0D%0A4&fields=email,picture&disclosure_shown_for=email,picture

כשהשרת מקבל את הבקשה, הוא צריך:

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

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

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

נכס תיאור
token אסימון הוא מחרוזת שמכילה הצהרות לגבי האימות.
continue_on כתובת URL להפניה אוטומטית שמאפשרת תהליך כניסה עם כמה שלבים.

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

  {
    // IdP can respond with a token to authenticate the user
    "token": "***********"
  }

המשך בתכונה

ספק הזהויות יכול לספק כתובת URL להפניה אוטומטית בתשובה של נקודת הקצה של הצהרת הזהות כדי לאפשר תהליך כניסה רב-שלבי. האפשרות הזו שימושית כשספק הזהויות צריך לבקש מידע נוסף או הרשאות נוספות, למשל:

  • הרשאה לגשת למשאבים בצד השרת של המשתמש.
  • אימות לכך שהפרטים ליצירת קשר עדכניים.
  • אמצעי בקרת הורים.

נקודת הקצה של הצהרת הזהות יכולה להחזיר מאפיין 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 popup window:
    "continue_on": "https://idp.example/continue_on_url"
  }

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

  IdentityProvider.close();

כדי שה-API של Continuation יפעל, נדרשת אינטראקציה מפורשת של המשתמש (קליקים). כך פועל Continuation API במצבי גישור שונים:

  • במצב passive:
    • mediation: 'optional' (ברירת מחדל): Continuation API יפעל רק עם תנועת משתמש, כמו לחיצה על לחצן בדף או בממשק המשתמש של FedCM. כשמופעל אימות מחדש אוטומטי ללא תנועת משתמש, לא נפתח חלון קופץ וההבטחה נדחית.
    • mediation: 'required': תמיד מבקש מהמשתמש לבצע אינטראקציה, כך שממשק ה-API של ההמשכיות תמיד פועל.
  • במצב פעיל:
    • תמיד נדרשת הפעלת משתמש. ה-Continuation API תמיד תואם.

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

  IdentityProvider.resolve(token, {accountId: '1234');

החזרת תגובת שגיאה

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

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

תוויות חשבון בהתאמה אישית

באמצעות תוויות חשבון בהתאמה אישית, ספק הזהויות יכול להוסיף הערות לחשבונות משתמשים באמצעות תוויות, וספק השירות יכול לבחור לאחזר רק חשבונות עם תוויות ספציפיות על ידי ציון configURL עבור התווית הספציפית הזו. האפשרות הזו שימושית כשספק הזהויות צריך לסנן חשבונות לפי קריטריונים ספציפיים, למשל כדי להציג רק חשבונות ספציפיים לתפקיד כמו "developer" או "hr".

אפשר לבצע סינון דומה באמצעות התכונות Domain Hint ו-Login Hint, על ידי ציון שלהן בקריאה navigator.credentials.get(). עם זאת, תוויות חשבון בהתאמה אישית יכולות לסנן משתמשים על ידי ציון קובץ ההגדרות, וזה שימושי במיוחד כשמשתמשים במספר configURLs. תוויות חשבון בהתאמה אישית שונות גם בכך שהן מסופקות משרת ה-IdP, ולא מה-RP, כמו רמזים להתחברות או לדומיין.

נניח שספק הזהויות רוצה להבדיל בין חשבונות "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"
  }
  • בהגדרה כזו, קובץ ה-well-known צריך לכלול את הערכים accounts_endpoint ו-login_url כדי לאפשר שימוש בכמה configURL:
  {
    "provider_urls": [ "https://idp.example/fedcm.json" ],
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }
  • נקודת הקצה של החשבונות של ספק הזהויות הנפוץ (במקרה הזה 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"]
    }]
  }

כשספק זהויות רוצה לאפשר למשתמשי "hr" להיכנס לחשבון, הוא יכול לציין את https://idp.example/hr/fedcm.json configURL בקריאה 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 חוצת מקורות עם קובצי Cookie עם SameSite=None וסוג תוכן של application/x-www-form-urlencoded לנקודת הקצה של הניתוק הזו עם הפרטים הבאים:

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

כשהשרת מקבל את הבקשה, הוא צריך:

  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"
  }

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

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

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

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

  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

כשהשרת מקבל את הבקשה, הוא צריך:

  1. קובעים את נקודת ההסתמכות של client_id.
  2. שולחים תשובה עם המטא-נתונים של הלקוח.

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

נכס תיאור
ֶprivacy_policy_url (אופציונלי) כתובת ה-URL של מדיניות הפרטיות של ספק שירותי הפלטפורמה.
ֶterms_of_service_url (אופציונלי) כתובת ה-URL של התנאים וההגבלות של ספק התוכן.
ֶ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
      }]
  }

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

כתובת URL להתחברות

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

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

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

תיבת דו-שיח של FedCM שמציעה להיכנס לחשבון בספק הזהויות.
תיבת דו-שיח של FedCM עם הצעה להיכנס ל-IdP.

כשהמשתמש לוחץ על הלחצן המשך, בדפדפן נפתח חלון קופץ של דף הכניסה של ספק הזהויות.

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

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

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

דיווח לדפדפן על סטטוס הכניסה של המשתמש

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

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

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

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

  Set-Login: logged-in

לחלופין, אפשר לקרוא לשיטת JavaScript‏ navigator.login.setStatus('logged-in') ממקור ספק הזהויות בניווט ברמה העליונה:

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

סטטוס ההתחברות של המשתמש יוגדר כlogged-in.

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

  Set-Login: logged-out

אפשרות אחרת היא להפעיל את JavaScript API‏ navigator.login.setStatus('logged-out') ממקור ספק הזהויות בניווט ברמה העליונה:

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

סטטוס ההתחברות של המשתמש יוגדר כlogged-out.

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

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

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

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

השלבים הבאים

מטמיעים את FedCM ב-RPs ומפיצים את ה-SDK של JavaScript. אין צורך להטמיע את ה-RP בעצמכם, כך שתוכלו לשמור על עדכניות שלהם.
איך מגדירים את הסביבה ומאתרים באגים בהטמעה