הטמעת פתרון זהויות באמצעות FedCM

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

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

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

בעלי תוכן דיגיטלי צריכים לבצע את השלבים הבאים כדי להפעיל את FedCM באתר שלהם:

הטמעת FedCM כ-IdP

מידע נוסף על השלבים להטמעת FedCM בצד ה-IdP

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

כדי למנוע משירותי מעקב לנצל לרעה את ה-API, צריך להציג קובץ well-known מ-/.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. דוגמה לתוכן של קובץ well-known:

  {
    "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 מספק רשימה של נקודות קצה נדרשות לדפדפן. שירותי 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 והיא לא עוקבת אחרי הפניות אוטומטיות. כך אפשר למנוע מה-IdP לדעת מי שלח את הבקשה ואיזה 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" יחזרו.
ֶ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 מציין רק את קובץ התצורה שבו יש להשתמש.

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

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

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

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

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

הטמעת FedCM כגורם מוגבל (RP)

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

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

  if ('IdentityCredential' in window) {
    // If the feature is available, take action
  } else {
    // FedCM is not supported, use a different identity solution
  }

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

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

מאפיין הקשר

באמצעות המאפיין האופציונלי context, ה-RP יכול לשנות את המחרוזת בממשק המשתמש של תיבת הדו-שיח של FedCM (לדוגמה, 'כניסה אל rp.example…', 'שימוש ב-idp.example…') כדי להתאים להקשרי אימות מוגדרים מראש, למשל. המאפיין context יכול לקבל את הערכים הבאים:

  • signin (ברירת מחדל)
  • signup
  • use
תרשים שמסביר את רכיבי ממשק המשתמש של תיבת הדו-שיח של FedCM: בצד ימין למעלה מוצג סמל. מימין לסמל מופיע רכיב הקשר שבו מוצגת ההודעה 'כניסה ל-RP באמצעות IdP'. בתחתית המסך מופיע הלחצן 'המשך' עם טקסט וצבע רקע בהתאמה אישית.
איך הלוגו מוצג בתיבת הדו-שיח של FedCM

לדוגמה, הגדרת context ל-use תוביל להודעה הבאה:

תיבת דו-שיח של FedCM עם הודעת הקשר בהתאמה אישית: במקום 'כניסה' באמצעות FedCM, הודעת ההקשר היא 'שימוש' ב-FedCM.
תיבת דו-שיח של FedCM עם הודעת הקשר בהתאמה אישית.

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

המאפיין Providers

הנכס providers מקבל מערך של אובייקטים מסוג IdentityProvider שיש להם את המאפיינים הבאים:

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

הערה: הפרמטר mode נתמך החל מגרסה 132 של Chrome.
ֶfields (אופציונלי) מערך של מחרוזות שמציין את פרטי המשתמש ('name',‏ 'email',‏ 'picture') ש-RP צריך ש-IdP ישתף איתו.
הערה: Field API נתמך ב-Chrome מגרסה 132 ואילך.
ֶparameters (אופציונלי) אובייקט מותאם אישית שמאפשר לציין פרמטרים נוספים של מפתח/ערך:
  • scope: ערך מחרוזת שמכיל הרשאות נוספות ש-RP צריך לבקש, לדוגמה "drive.readonly calendar.readonly"
  • nonce: מחרוזת אקראית כדי להבטיח שהתגובה תישלח עבור הבקשה הספציפית הזו. מניעת התקפות שחזור.
  • פרמטרים מותאמים אישית אחרים של מפתח/ערך.

הערה: התמיכה ב-parameters מתחילה ב-Chrome 132.

מצב פעיל

FedCM תומך בהגדרות שונות של סטטוס UX. מצב פסיבי הוא מצב ברירת המחדל, והמפתחים לא צריכים להגדיר אותו.

כדי להשתמש ב-FedCM במצב פעיל:

  1. בודקים את הזמינות של התכונה בדפדפן של המשתמש.
  2. קריאה ל-API באמצעות תנועת משתמש זמנית, כמו לחיצה על לחצן.
  3. מעבירים את הפרמטר mode לקריאה ל-API:
  let supportsFedCmMode = false;
  try {
    navigator.credentials.get({
      identity: Object.defineProperty(
        // Check if this Chrome version supports the Mode API.
        {}, 'mode', {
          get: function () { supportsFedCmMode = true; }
        }
      )
    });
  } catch(e) {}

  if (supportsFedCmMode) {
    // The button mode is supported. Call the API with mode property:
    return await navigator.credentials.get({
      identity: {
        providers: [{
          configURL: 'https://idp.example/config.json',
          clientId: '123',
        }],
        // The 'mode' value defines the UX mode of FedCM.
        // - 'active': Must be initiated by user interaction (e.g., clicking a button).
        // - 'passive': Can be initiated without direct user interaction.
        mode: 'active'
      }
    });
  }

סמל מותאם אישית במצב פעיל

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

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

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

Login Hint API

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

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

  return await navigator.credentials.get({
    identity: {
      providers: [{
        configURL: 'https://idp.example/manifest.json',
        clientId: '123',
        // Accounts endpoint can specify a 'login_hints' array for an account.
        // When RP specifies a 'exampleHint' value, only those accounts will be
        // shown to the user whose 'login_hints' array contains the 'exampleHint'
        // value
        loginHint : 'exampleHint'
      }]
    }
  });

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

Domain Hint 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',
        // Accounts endpoint can specify a 'domain_hints' array for an account.
        // When RP specifies a '@domain.example' value, only those accounts will be
        // shown to the user whose 'domain_hints' array contains the
        // '@domain.example' value
        domainHint : '@domain.example'
      }]
    }
  });

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

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

פרמטרים מותאמים אישית

התכונה 'פרמטרים מותאמים אישית' מאפשרת ל-RP לספק פרמטרים נוספים של מפתח/ערך לנקודת הקצה של טענת הנכוֹנוּת (assertion) של הזהות. באמצעות Parameters API, ספקי ה-RP יכולים להעביר פרמטרים נוספים ל-IdP כדי לבקש הרשאות למשאבים מעבר לכניסה בסיסית. העברת פרמטרים נוספים יכולה להיות שימושית בתרחישים הבאים:

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

כדי להשתמש ב-API, ה-RP מוסיף פרמטרים לנכס params כאובייקט בקריאה navigator.credentials.get():

  let {token} = await navigator.credentials.get({
    identity: {
      providers: [{
        clientId: '1234',
        configURL: 'https://idp.example/fedcm.json',
        // Key/value pairs that need to be passed from the
        // RP to the IdP but that don't really play any role with
        // the browser.
        params: {
          IDP_SPECIFIC_PARAM: '1',
          foo: 'BAR'
        }
      },
    }
  });

הדפדפן יתרגם את זה באופן אוטומטי לבקשת POST ל-IdP עם פרמטרים כאובייקט יחיד של JSON שעבר סריאליזציה וקידוד ככתובת URL:

  // The assertion endpoint is drawn from the config file
  POST /fedcm_assertion_endpoint HTTP/1.1
  Host: idp.example
  Origin: https://rp.example/
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

  // params are translated into urlencoded version of `{"IDP_SPECIFIC_PARAM":"1","foo":"bar"}`
  account_id=123&client_id=client1234&params=%22%7B%5C%22IDP_SPECIFIC_PARAM%5C%22%3A1%2C%5C%22foo%5C%22%3A%5C%22BAR%5C%22%7D%22.

אם ל-RP נדרשות הרשאות נוספות, ה-IdP יכול לספק קישור להפניה אוטומטית. לדוגמה, ב-node.js:

  if (rpRequestsPermissions) {
    // Response with a URL if the RP requests additional permissions
    return res.json({
      continue_on: '/example-redirect',
    });
  }

שדות

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

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

כדי להשתמש בתכונה 'שדות', RP צריך להוסיף מערך fields בקריאה ל-navigator.credentials.get(). השדות יכולים להכיל כל שילוב של name, ‏ email ו-picture. בעתיד נוכל להרחיב את האפשרויות האלה כך שיכללו ערכים נוספים. בקשה עם fields תיראה כך:

  let { token } = await navigator.credentials.get({
    identity: {
      providers: [{
        // RP requests the IdP to share only user email and profile picture
        fields: [ 'email', 'picture'],
        clientId: '1234',
        configURL: 'https://idp.example/fedcm.json',

      },
    }
  });

הדפדפן יתרגם אותו באופן אוטומטי לבקשת HTTP לנקודת הקצה של טענת הנכוֹנוּת של הזהות, שכוללת את הפרמטר fields שצוין על ידי RP, עם השדות שהדפדפן חשף למשתמש בפרמטר disclosure_shown_for. מטעמי תאימות לאחור, הדפדפן ישלח גם את הערך disclosure_text_shown=true אם טקסט הגילוי הנאות הוצג והשדות המבוקשים כוללים את כל שלושת השדות: 'name',‏ 'email' ו-'picture'.

  POST /id_assertion_endpoint HTTP/1.1
  Host: idp.example
  Origin: https://rp.example/
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

  // The RP only requested to share email and picture. The browser will send `disclosure_text_shown=false`, as the 'name' field value is missing
  account_id=123&client_id=client1234&disclosure_text_shown=false&fields=email,picture&disclosure_shown_for=email,picture

אם fields הוא מערך ריק, סוכן המשתמש ידלג על ממשק המשתמש של הגילוי הנאות.

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

זה קורה גם אם התגובה מנקודת הקצה accounts לא מכילה מזהה לקוח שתואם ל-RP ב-approved_clients.

במקרה כזה, הערך של disclosure_text_shown שנשלח אל נקודת הקצה של טענת הנכוֹנוּת של הזהות הוא false בגוף ה-HTTP:

  POST /id_assertion_endpoint HTTP/1.1
  Host: 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=234234&disclosure_text_shown=false

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

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