עדכונים של FedCM: גרסאות מקור לניסיון של חבילת Continuation API והענקה אוטומטית של Storage Access API

החל מ-Chrome 126, מפתחים יכולים להתחיל להריץ גרסת טרום-השקה (origin) של חבילה של תכונות Federated Credential Management API (FedCM) למחשב, שמאפשרות תרחישים לדוגמה מסוימים של הרשאה. החבילה מורכבת מ-Continuation API ומ-Parameters API, שמאפשרים חוויה דומה לתהליך ההרשאה של OAuth, שכוללת תיבת דו-שיח של הרשאה שמספקת ספק זהויות (IdP). החבילה כוללת גם שינויים אחרים, כמו Fields API, כמה כתובות URL של הגדרות ותווית חשבון בהתאמה אישית. החל מגרסה 126 של Chrome, אנחנו משיקים גם גרסת טרום-השקה של Storage Access API‏ (SAA) שמאשרת באופן אוטומטי בקשות SAA אם המשתמש נכנס לחשבון באמצעות FedCM בעבר.

גרסת מקור לניסיון: חבילת FedCM Continuation API

חבילת ה-API של FedCM Continuation מורכבת מכמה תוספים של FedCM:

Continuation API

משתמש נכנס לחשבון ב-RP ולאחר מכן נותן הרשאה באמצעות מצב הלחצן.

אתם יכולים לבדוק דמו של ה-API ב-Glitch.

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

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

{
  "token": "***********"
}

עם זאת, באמצעות Continuation API, נקודת הקצה של טענת הנכוֹנוּת של הזהות יכולה להחזיר מאפיין 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 pop-up window:
  "continue_on": "/oauth/authorize?scope=..."
}

ברגע שהדפדפן מקבל את התגובה continue_on, נפתח חלון קופץ חדש שמנחה את המשתמש לנתיב שצוין.

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

document.getElementById('allow_btn').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.close().

IdentityProvider.close();

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

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

Parameters API

Parameters API מאפשר ל-RP לספק פרמטרים נוספים לנקודת הקצה של טענת הנכוֹנוּת של הזהות. באמצעות Parameters API, ספקי ה-RP יכולים להעביר פרמטרים נוספים ל-IdP כדי לבקש הרשאות למשאבים מעבר לכניסה בסיסית. המשתמש יאשר את ההרשאות האלה דרך תהליך UX שנשלט על ידי IdP, שמופעל דרך Continuation API.

כדי להשתמש ב-API, מוסיפים פרמטרים לנכס 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',
        ETC: 'MOAR',
        scope: 'calendar.readonly photos.write',
      }
    },
  }
});

שמות המאפיינים באובייקט params מתחילים ב-param_. בדוגמה שלמעלה, המאפיין params מכיל את IDP_SPECIFIC_PARAM בתור '1', את foo בתור 'BAR', את ETC בתור 'MOAR' ואת scope בתור 'calendar.readonly photos.write'. הערך הזה יתורגם כ-param_IDP_SPECIFIC_PARAM=1&param_foo=BAR&param_ETC=MOAR&param_scope=calendar.readonly%20photos.write בגוף ה-HTTP של הבקשה:

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

account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=false&param_IDP_SPECIFIC_PARAM=1&param_foo=BAR&param_ETC=MOAR&param_scope=calendar.readonly%20photos.write

אחזור הרשאות באופן דינמי

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

כדי לבקש הרשאה באופן דינמי באמצעות FedCM, ה-IdP יכול:

  1. קוראים ל-navigator.credentials.get() עם הפרמטרים הנדרשים שה-IdP יכול להבין, כמו scope.
  2. נקודת הקצה של טענת הנכוֹנוּת של הזהות מאשרת שהמשתמש כבר נכנס לחשבון ומגיבה עם כתובת URL מסוג continue_on.
  3. הדפדפן יפתח חלון קופץ עם דף ההרשאות של ה-IdP, שבו תתבקשו להעניק הרשאה נוספת שתואמת להיקפים המבוקשים.
  4. אחרי שה-IdP מאשר את הבקשה דרך IdentityProvider.resolve(), החלון נסגר וקריאת ה-navigator.credentials.get() המקורית של ה-RP מקבלת אסימון רלוונטי או קוד הרשאה, כדי שה-RP יוכל להחליף אותו באסימון גישה מתאים.

Fields API

Fields API מאפשר ל-RP להצהיר על מאפייני חשבון לבקש מה-IdP, כדי שהדפדפן יוכל להציג ממשק משתמש מתאים לגילוי נאות בתיבת הדו-שיח של FedCM. האחריות של ה-IdP היא לכלול את השדות המבוקשים בטוקן המוחזר. אפשר להתייחס לבקשה ל'פרופיל בסיסי' ב-OpenID Connect לעומת 'היקפי הרשאות' ב-OAuth.

הודעת הגילוי הנאות במצב ווידג'ט.
הודעה לגבי גילוי נאות במצב ווידג'ט.
הודעת גילוי נאות במצב כפתור.
הודעה לגבי גילוי נאות במצב לחצן.

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

בקשה עם fields תיראה כך:

let { token } = await navigator.credentials.get({
  identity: {
    providers: [{
      fields: ['name', 'email', 'picture'],
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      params: {
        scope: 'drive.readonly calendar.readonly',
      }
    },
  }
  mediation: 'optional',
});

בקשת ה-HTTP לנקודת הקצה של טענת הנכוֹנוּת (assertion) של הזהות כוללת את הפרמטר fields שצוין על ידי ה-RP, כאשר הפרמטר disclosure_text_shown מוגדר כ-true אם מדובר לא במשתמש חוזר, ואת השדות שהדפדפן חשף למשתמש בפרמטר disclosure_shown_for:

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=true&fields=email,name,picture&disclosure_shown_for=email,name,picture

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

אם fields הוא מערך ריק, הבקשה תיראה כך:

let { token } = await navigator.credentials.get({
  identity: {
    providers: [{
      fields: [],
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      params: {
        scope: 'drive.readonly calendar.readonly',
      }
    },
  }
  mediation: 'optional',
});

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

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

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

כמה configURLs

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

אם הוספת את accounts_endpoint ו-login_url לקובץ ה-well-known, המערכת תתעלם מ-provider_urls כדי שה-IdP יוכל לתמוך בכמה קובצי תצורה. אם לא, הערך של provider_urls ימשיך לפעול כדי לשמור על תאימות לאחור.

קובץ ה-well-known שתומך בכמה configURLs יכול להיראות כך:

{
  "provider_urls": [ "https://idp.example/fedcm.json" ],
  "accounts_endpoint": "https://idp.example/accounts",
  "login_url": "https://idp.example/login"
}

כך אנחנו יכולים:

  1. לשמור על תאימות לאחור ולפנים עם קבצים קיימים ידועים ועם הגרסאות הקודמות של הדפדפנים שכבר נפרסו.
  2. יש מספר שרירותי של קובצי תצורה, כל עוד כולם מפנים לאותו accounts_endpoint ו-login_url.
  3. אין אפשרות להוסיף אנטרופיה לבקשת האחזור עם פרטי הכניסה שנשלחת אל accounts_endpoint, כי צריך לציין אותה ברמה '‎.well-known'.

התמיכה בכמה configURLs היא אופציונלית, וההטמעות הקיימות של FedCM יכולות להישאר ללא שינוי.

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

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

דוגמה

IdP תומך בשתי כתובות configURL, אחת לצרכנים ואחת לארגונים. בקובץ התצורה של הצרכן יש תווית 'consumer', ובקובץ התצורה של הארגון יש תווית 'enterprise'.

בהגדרה כזו, הקובץ הידוע כולל את accounts_endpoint ואת login_url כדי לאפשר כמה configURLs.

{
  "provider_urls": [ "https://idp.example/fedcm.json" ],
  "accounts_endpoint": "https://idp.example/accounts",
  "login_url": "https://idp.example/login"
}

כשה-accounts_endpoint מסופק בקובץ ה-well-known, המערכת מתעלמת מה-provider_urls. ה-RP יכול להפנות ישירות לקובצי התצורה המתאימים בקריאה ל-navigator.credentials.get().

קובץ התצורה של הצרכן נמצא ב-https://idp.example/fedcm.json, והוא כולל את המאפיין accounts שמציין את 'consumer' באמצעות include.

{
  "accounts_endpoint": "https://idp.example/accounts",
  "client_metadata_endpoint": "/client_metadata",
  "login_url": "https://idp.example/login",
  "id_assertion_endpoint": "/assertion",
  "accounts": {
    "include": "consumer"
  }
}

קובץ התצורה הארגוני נמצא ב-https://idp.example/enterprise/fedcm.json, והוא כולל את המאפיין accounts שמציין את 'enterprise' באמצעות include.

{
  "accounts_endpoint": "https://idp.example/accounts",
  "client_metadata_endpoint": "/enterprise/client_metadata",
  "login_url": "https://idp.example/login",
  "id_assertion_endpoint": "/assertion",
  "accounts": {
    "include": "enterprise"
  }
}

נקודת הקצה המשותפת של חשבונות ה-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": ["consumer"]
  }], [{
   "id": "4567",
   "given_name": "Jane",
   "name": "Jane Doe",
   "email": "jane_doe@idp.example",
   "picture": "https://idp.example/profile/4567",
   "labels": ["enterprise"]
  }]
}

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

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

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

גרסת המקור לניסיון: FedCM כאות אמון ל-Storage Access API

ב-Chrome 126 אנחנו מתחילים גרסת מקור לניסיון של FedCM כאות אמון ל-Storage Access API. בעקבות השינוי הזה, הענקת הרשאה מראש דרך FedCM הופכת לסיבה תקפה לאישור אוטומטי של בקשת גישה לאחסון על ידי ממשקי ה-API של גישה לאחסון.

האפשרות הזו שימושית כש-iframe מוטמע רוצה לגשת למשאבים מותאמים אישית: לדוגמה, אם idp.example מוטמע ב-rp.example וצריך להציג משאב מותאם אישית. אם הדפדפן מגביל את הגישה לקובצי cookie של צד שלישי, גם אם המשתמש נכנס ל-rp.example באמצעות idp.example עם FedCM, ה-iframe המוטמע של idp.example לא יוכל לבקש משאבים מותאמים אישית כי הבקשות לא יכללו קובצי cookie של צד שלישי.

כדי לעשות זאת, ל-idp.example צריכה להיות הרשאת גישה לאחסון דרך ה-iframe המוטמע באתר, ואפשר לקבל אותה רק באמצעות בקשה להרשאה.

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

// In top-level rp.example:

// Ensure FedCM permission has been granted.
const cred = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: 'https://idp.example/fedcm.json',
      clientId: '123',
    }],
  },
  mediation: 'optional',
});

// In an embedded IdP iframe:

// No user gesture is needed to call this, and the call will be auto-granted.
await document.requestStorageAccess();

// This returns `true`.
const hasAccess = await document.hasStorageAccess();

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

השתתפות בגרסת המקור לניסיון

כדי לנסות את חבילת FedCM Continuation API באופן מקומי, מפעילים דגל של Chrome chrome://flags#fedcm-authz ב-Chrome מגרסה 126 ואילך. אפשר גם לנסות את FedCM בתור אות אמון ל-Storage Access API באופן מקומי, על ידי הפעלת #fedcm-with-storage-access-api ב-Chrome בגרסה 126 ואילך.

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

כדי לנסות את גרסת המקור לניסיון של חבילת FedCM Continuation API, צריך ליצור שני אסימוני ניסיון למקור:

אם אתם רוצים להפעיל את Continuation API יחד עם תהליך הלחצן, עליכם להפעיל גם את גרסת ה-API לניסיון של Button Mode API:

כדי לנסות את FedCM כאות אמון לגרסת המקור של Storage Access API:

גרסת המקור לניסיון של חבילת Continuation API ו-FedCM כאות אמון לגרסת המקור לניסיון של Storage Access API זמינות מגרסת Chrome 126.

הרשמה של תקופת ניסיון למקור של צד שלישי ל-RP

  1. עוברים לדף הרישום לגרסת הטרום-השקה.
  2. לוחצים על הלחצן Register וממלאים את הטופס כדי לבקש אסימון.
  3. מזינים את המקור של ה-IdP כמקור אינטרנט.
  4. בודקים את האפשרות 'התאמה לצד שלישי' כדי להחדיר את האסימון באמצעות JavaScript במקורות אחרים.
  5. לוחצים על שליחה.
  6. להטמיע את האסימון שהונפק באתר של צד שלישי.

כדי להטמיע את האסימון באתר של צד שלישי, מוסיפים את הקוד הבא לספריית JavaScript או ל-SDK של ה-IdP שמוצגים מהמקור של ה-IdP.

const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);

מחליפים את TOKEN_GOES_HERE באסימון משלכם.