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

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

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

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

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

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

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

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

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

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

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

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

  • ספק IdP צריך לתמוך במספר הגדרות שונות לבדיקה ולייצור.
  • ספק זהויות צריך לתמוך בהגדרות שונות לכל אזור (לדוגמה, eu-idp.example ו-us-idp.example).

כדי לתמוך במספר הגדרות (לדוגמה, כדי להבדיל בין סביבה לבדיקה לבין סביבה לייצור), ה-IdP צריך לציין את accounts_endpoint ואת login_url:

  {
    // This property is required, but will be ignored when IdP supports
    // multiple configs (when `accounts_endpoint` and `login_url` are
    // specified), as long as `accounts_endpoint` and `login_url` in
    // that config file match those in the well-known file.
    "provider_urls": [ "https://idp.example/fedcm.json" ],

    // Specify accounts_endpoint and login_url properties to support
    // multiple config files.
    // Note: The accounts_endpoint and login_url must be identical
    // across all config files. Otherwise,
    // the configurations won't be supported.
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }

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

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

ה-RP מעביר את כתובת ה-URL של קובץ התצורה לקריאה ל-FedCM API כדי לאפשר למשתמש להיכנס:

  // Executed on RP's side:
  const credential = await navigator.credentials.get({
    identity: {
      context: 'signup',
      providers: [{
        // To allow users to sign in with an IdP using FedCM, RP specifies the IdP's config file URL:
        configURL: 'https://accounts.idp.example/fedcm.json',
        clientId: '********',
  });
  const { token } = credential;

הדפדפן יאתר את קובץ התצורה באמצעות בקשת GET ללא הכותרת Origin או הכותרת Referer. לבקשה אין קובצי cookie והיא לא עוקבת אחרי הפניות אוטומטיות. כך, ספק הזהויות לא יכול לדעת מי שלח את הבקשה ואיזה RP מנסה להתחבר. לדוגמה:

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

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

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

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

הערה: התמיכה בתוויות חשבון בהתאמה אישית מתחילה ב-Chrome 132.
ֶ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 או שווה לו במצב פעיל.
modes אובייקט שמכיל מפרטים לגבי אופן הצגת ממשק המשתמש של FedCM במצבים שונים:
  • active
  • passive
modes.active אובייקט שמכיל מאפיינים שמאפשרים להתאים אישית את ההתנהגות של FedCM במצב ספציפי. גם modes.active וגם modes.passive יכולים להכיל את הפרמטר הבא:
  • supports_use_other_account: ערך בוליאני שמציין אם המשתמש יכול להיכנס באמצעות חשבון שונה מהחשבון שבו הוא מחובר כרגע (אם ה-IdP תומך בכמה חשבונות).

הערה: התכונה 'שימוש בחשבון אחר' והמצב הפעיל נתמכים בגרסה 132 של Chrome ואילך.
modes.passive

זוהי דוגמה לגוף תגובה מה-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.
    "accounts": {"include": "developer"},
    "modes": {
        "active": {
          "supports_use_other_account": true,
        }
    },
    "branding": {
      "background_color": "green",
      "color": "#FFEEAA",
      "icons": [{
        "url": "https://idp.example/icon.ico",
        "size": 25
      }]
    }
  }

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

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

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

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

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

  {
    "accounts_endpoint" : "/accounts.example",
    "modes": {
      "active": {
        // Allow the user to choose other account (false by default)
        "supports_use_other_account": true
      }
      // "passive" mode can be configured separately
    }
  }

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

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

הדפדפן שולח בקשת 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 (חובה) השם הפרטי ושם המשפחה של המשתמש.
email (חובה) כתובת האימייל של המשתמש.
ֶgiven_name (אופציונלי) השם הפרטי של המשתמש.
ֶpicture (אופציונלי) כתובת ה-URL של תמונת הדמות של המשתמש.
ֶapproved_clients (אופציונלי) מערך של מזהי לקוח של RP שהמשתמש רשם.
ֶlogin_hints (אופציונלי) מערך של כל סוגי המסננים האפשריים ש-IdP תומך בהם כדי לציין חשבון. ה-RP יכול להפעיל את navigator.credentials.get() עם המאפיין loginHint כדי להציג באופן סלקטיבי את החשבון שצוין.
ֶdomain_hints (אופציונלי) מערך של כל הדומיינים שהחשבון משויך אליהם. ה-RP יכול להפעיל את navigator.credentials.get() עם נכס domainHint כדי לסנן את החשבונות.
ֶlabels (אופציונלי) מערך של מחרוזות של תוויות חשבון בהתאמה אישית שחשבון משויך אליהן.
שירות IdP יכול להטמיע תיוג חשבונות בהתאמה אישית באופן הבא:
  • מציינים תוויות של חשבונות בנקודת הקצה accounts (באמצעות הפרמטר labels).
  • יוצרים קובץ תצורה לכל תווית ספציפית.

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

תוויות חשבון בהתאמה אישית שונות מהטיפ לכניסה ומהטיפ לדומיין, כך ששרת ה-IdP מנהל אותן באופן מלא, וה-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.
      "labels": ["hr", "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.

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

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

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

הערה: הפרמטר Fields נתמך החל מגרסה 132 של Chrome.
ֶparams (אופציונלי) כל אובייקט JSON תקין שמאפשר לציין פרמטרים נוספים של מפתח/ערך בהתאמה אישית, לדוגמה:
  • scope: ערך מחרוזת שמכיל הרשאות נוספות ש-RP צריך לבקש, לדוגמה "drive.readonly calendar.readonly"
  • nonce: מחרוזת אקראית שסופקת על ידי RP כדי להבטיח שהתגובה תישלח לגבי הבקשה הספציפית הזו. מניעת התקפות שחזור.
  • פרמטרים מותאמים אישית אחרים של מפתח/ערך.
כשהדפדפן שולח בקשת 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&disclosure_text_shown=true&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 יכול להחליט איך להנפיק את האסימון. באופן כללי, הוא חתום על ידי מידע כמו מזהה החשבון, מזהה הלקוח, מקור המנפיק ומזהה חד-פעמי (nonce), כדי ש-RP יוכל לאמת שהטוקן הוא מקורי.

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

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

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

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

התכונה 'המשך'

ה-IdP יכול לספק כתובת URL להפניה אוטומטית בתשובה של נקודת הקצה של טענת הנכוֹנוּת (assertion) של הזהות כדי לאפשר תהליך כניסה בן כמה שלבים. האפשרות הזו שימושית כש-IdP צריך לבקש מידע נוסף או הרשאות נוספות, לדוגמה:

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

נקודת הקצה של טענת הנכוֹנוּת של התעודה המזהה יכולה להחזיר מאפיין continue_on שכולל נתיב מוחלט או יחסי לנקודת הקצה של טענת הנכוֹנוּת של התעודה המזהה.

  {
    // In the id_assertion_endpoint, instead of returning a typical
    // "token" response, the IdP decides that it needs the user to
    // continue on a popup window:
    "continue_on": "https://idp.example/continue_on_url"
  }

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

  IdentityProvider.close();

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

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

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

  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 ייצור את ממשק המשתמש של השגיאה עם הודעת שגיאה כללית ויעביר את הקוד ל-RP.
  • url: הוא מזהה דף אינטרנט שקריא לאנשים עם מידע על השגיאה, כדי לספק למשתמשים מידע נוסף עליה. השדה הזה שימושי למשתמשים כי הדפדפנים לא יכולים לספק הודעות שגיאה עשירות בממשק משתמש מובנה. לדוגמה: קישורים לשלבים הבאים או פרטים ליצירת קשר עם שירות הלקוחות. אם משתמש רוצה לקבל מידע נוסף על פרטי השגיאה ועל הדרך לתקן אותה, הוא יכול להיכנס לדף שסופק מתוך ממשק המשתמש של הדפדפן. כתובת ה-URL צריכה להיות באותו אתר כמו ה-IdP configURL.
  // id_assertion_endpoint response
  {
    "error" : {
      "code": "access_denied",
      "url" : "https://idp.example/error?type=access_denied"
    }
  }

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

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

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

נניח ש-IdP רוצה להבדיל בין חשבונות "developer" לבין חשבונות "hr". כדי לעשות זאת, ה-IdP צריך לתמוך בשתי כתובות configURL עבור "developer" ו-"hr", בהתאמה:

  • קובץ התצורה של המפתח https://idp.example/developer/fedcm.json כולל את התווית "developer", וקובץ התצורה הארגוני https://idp.example/hr/fedcm.json כולל את התווית "hr", באופן הבא:
  // The developer config file at `https://idp.example/developer/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "accounts": {
      // Account label
      "include": "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",
    "accounts": {
      // Account label
      "include": "hr"
    }
  }
  • בהגדרה כזו, הקובץ הידוע צריך לכלול את accounts_endpoint ואת login_url כדי לאפשר כמה configURLs:
  {
    "provider_urls": [ "https://idp.example/fedcm.json" ],
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }
  • נקודת הקצה (endpoint) של חשבונות המשותפת ל-IdP (בדוגמאות האלה היא https://idp.example/accounts) מחזירה רשימה של חשבונות שכוללת את הנכס labels עם תוויות שהוקצו במערך לכל חשבון:
  {
  "accounts": [{
    "id": "123",
    "given_name": "John",
    "name": "John Doe",
    "email": "john_doe@idp.example",
    "picture": "https://idp.example/profile/123",
    "labels": ["developer"]
    }], [{
    "id": "4567",
    "given_name": "Jane",
    "name": "Jane Doe",
    "email": "jane_doe@idp.example",
    "picture": "https://idp.example/profile/4567",
    "labels": ["hr"]
    }]
  }

כש-RP רוצה לאפשר למשתמשים ב-"hr" להיכנס לחשבון, הוא יכול לציין את ה-configURL‏ https://idp.example/hr/fedcm.json בקריאה navigator.credentials.get():

  let { token } = await navigator.credentials.get({
    identity: {
      providers: [{
        clientId: '1234',
        nonce: '234234',
        configURL: 'https://idp.example/hr/fedcm.json',
      },
    }
  });

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

  • תוויות הן מחרוזות. אם המערך labels או השדה include מכילים משהו שאינו מחרוזת, המערכת תתעלם ממנו.
  • אם לא יצוינו תוויות ב-configURL, כל החשבונות יוצגו בבורר החשבונות של FedCM.
  • אם לא צוינו תוויות לחשבון, הוא יוצג בבורר החשבונות רק אם גם ב-configURL לא צוינה תווית.
  • אם אין חשבון שמתאים לתווית המבוקשת במצב פסיבי (בדומה לתכונה 'רמז לדומיין'), בתיבת הדו-שיח של FedCM תוצג בקשה להתחברות, שמאפשרת למשתמש להיכנס לחשבון IdP. במצב פעיל, חלון הקופץ של ההתחברות נפתח ישירות.

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

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

נכס תיאור
account_hint רמז לחשבון ה-IdP.
client_id מזהה הלקוח של RP.
  POST /disconnect.example HTTP/1.1
  Host: idp.example
  Origin: rp.example
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x123
  Sec-Fetch-Dest: webidentity

  account_hint=account456&client_id=rp123

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

  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, צריך להעביר מחרוזת שלא תואמת למספר חשבון כלשהו, למשל "*".

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

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

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

נכס תיאור
ֶprivacy_policy_url (אופציונלי) כתובת ה-URL של מדיניות הפרטיות של RP.
ֶterms_of_service_url (אופציונלי) כתובת ה-URL של התנאים וההגבלות של RP.
ֶicons (אופציונלי) מערך של אובייקטים, כמו [{ "url": "https://rp.example/rp-icon.ico", "size": 40}]

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

  {
    "privacy_policy_url": "https://rp.example/privacy_policy.html",
    "terms_of_service_url": "https://rp.example/terms_of_service.html",
    "icons": [{
          "url": "https://rp.example/rp-icon.ico",
          "size": 40
      }]
  }

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

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

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

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

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

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

  Set-Login: logged-in

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

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

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

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

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

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

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

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

השלבים הבאים

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