การติดตั้งใช้งาน FedCM มีขั้นตอนหลักหลายขั้นตอนสําหรับทั้ง ผู้ให้บริการข้อมูลประจําตัว (IdP) และบุคคลที่สาม (RP) โปรดดูเอกสารประกอบเพื่อดูวิธีใช้ FedCM ในฝั่ง RP
IdPs ต้องทำตามขั้นตอนต่อไปนี้เพื่อติดตั้งใช้งาน FedCM
- สร้างไฟล์ที่รู้จักกันดี
- สร้างไฟล์การกำหนดค่า
- สร้างปลายทางต่อไปนี้
- แจ้งสถานะการเข้าสู่ระบบของผู้ใช้ให้เบราว์เซอร์ทราบ
สร้างไฟล์ที่รู้จักกันดี
เพื่อป้องกันไม่ให้เครื่องมือติดตามละเมิด 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เดียวกันหมายเหตุ: ระบบรองรับพารามิเตอร์นี้ตั้งแต่ Chrome 132 | 
| login_url | แนะนำ ต้องใช้ accounts_endpoint | URL หน้าเข้าสู่ระบบสำหรับให้ผู้ใช้ลงชื่อเข้าใช้ IdP ซึ่งจะช่วยให้รองรับการกำหนดค่าหลายรายการได้ ตราบใดที่ไฟล์กำหนดค่าแต่ละไฟล์ใช้ login_urlและaccounts_endpointเดียวกันหมายเหตุ: ระบบรองรับพารามิเตอร์นี้ตั้งแต่ Chrome 132 ขึ้นไป | 
เช่น หากมีการแสดงปลายทาง IdP ภายใต้
https://accounts.idp.example/ ปลายทางเหล่านั้นจะต้องแสดงไฟล์ .well-known ที่
https://idp.example/.well-known/web-identity รวมถึงไฟล์กำหนดค่า IdP
ตัวอย่างเนื้อหาไฟล์ที่รู้จักกันดีมีดังนี้
  {
    "provider_urls": ["https://accounts.idp.example/config.json"]
  }
IdP สามารถรองรับไฟล์กำหนดค่าหลายไฟล์สำหรับ IdP ได้โดยการระบุ
accounts_endpoint และ login_url ในไฟล์ที่รู้จักกันดี ฟีเจอร์นี้มีประโยชน์ในกรณีต่อไปนี้
- IdP ต้องรองรับการกำหนดค่าการทดสอบและการกำหนดค่าเวอร์ชันที่ใช้งานจริงที่แตกต่างกันหลายรายการ
- 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
ต้องโฮสต์ไฟล์กำหนดค่าอย่างน้อย 1 ไฟล์ รวมถึงปลายทางและ URL ที่จำเป็น การตอบกลับ JSON ทั้งหมด
ต้องแสดงโดยมีapplication/json content-type
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 คำขอไม่มีคุกกี้และไม่
ติดตามการเปลี่ยนเส้นทาง ซึ่งจะป้องกันไม่ให้ 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 สำหรับปลายทางบัญชี | 
| account_label(ไม่บังคับ) | สตริงป้ายกำกับบัญชีที่กำหนดเอง ซึ่งกำหนดว่าควรแสดงบัญชีใดเมื่อใช้ไฟล์กำหนดค่านี้ เช่น "account_label": "developer"IdP สามารถใช้การติดป้ายกำกับบัญชีที่กำหนดเองได้ดังนี้ 
 ตัวอย่างเช่น IdP จะใช้ "https://idp.example/developer-config.json"ไฟล์กำหนดค่าที่มี"account_label": "developer"ที่ระบุ นอกจากนี้ IdP ยังทำเครื่องหมายบัญชีบางบัญชีด้วยป้ายกำกับ"developer"โดยใช้พารามิเตอร์label_hintsในปลายทางของบัญชี เมื่อ RP เรียกใช้navigator.credentials.get()โดยระบุไฟล์กำหนดค่า"https://idp.example/developer-config.json"ระบบจะแสดงผลเฉพาะบัญชีที่มีป้ายกำกับ"developer"หมายเหตุ: ป้ายกำกับบัญชีที่กำหนดเองรองรับตั้งแต่ Chrome 132 | 
| supports_use_other_account(ไม่บังคับ) | บูลีนที่ระบุว่าผู้ใช้จะลงชื่อเข้าใช้ด้วยบัญชีอื่นที่แตกต่างจากบัญชีที่ใช้เข้าสู่ระบบได้หรือไม่ (หาก IdP รองรับหลายบัญชี) ซึ่งจะมีผลกับโหมดทำงานเท่านั้น | 
| client_metadata_endpoint(ไม่บังคับ) | URL สำหรับปลายทางข้อมูลเมตาของไคลเอ็นต์ | 
| id_assertion_endpoint(ต้องระบุ) | URL สำหรับปลายทางการยืนยันรหัส | 
| disconnect(ไม่บังคับ) | URL สำหรับปลายทางการยกเลิกการเชื่อมต่อ | 
| login_url(ต้องระบุ) | URL หน้าเข้าสู่ระบบสำหรับให้ผู้ใช้ลงชื่อเข้าใช้ IdP | 
| branding(ไม่บังคับ) | ออบเจ็กต์ที่มีตัวเลือกการสร้างแบรนด์ต่างๆ | 
| branding.background_color(ไม่บังคับ) | ตัวเลือกการสร้างแบรนด์ที่ตั้งค่าสีพื้นหลังของปุ่ม "ดำเนินการต่อในชื่อ..." ใช้ไวยากรณ์ CSS ที่เกี่ยวข้อง ได้แก่ hex-colorhsl()rgb()หรือnamed-color | 
| branding.color(ไม่บังคับ) | ตัวเลือกการสร้างแบรนด์ที่กำหนดสีข้อความของปุ่ม "ดำเนินการต่อในชื่อ..." ใช้ไวยากรณ์ CSS ที่เกี่ยวข้อง ได้แก่ hex-colorhsl()rgb()หรือnamed-color | 
| branding.icons(ไม่บังคับ) | อาร์เรย์ของออบเจ็กต์ไอคอน ไอคอนเหล่านี้จะแสดงในกล่องโต้ตอบการลงชื่อเข้าใช้ ออบเจ็กต์ไอคอนมีพารามิเตอร์ 2 รายการ ดังนี้ 
 | 
ต่อไปนี้คือตัวอย่างเนื้อหาการตอบกลับจาก 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
 
  ใช้บัญชีอื่น
ผู้ใช้สามารถเปลี่ยนไปใช้บัญชีอื่นที่ไม่ใช่บัญชีที่เข้าสู่ระบบ ได้ หาก IdP รองรับหลายบัญชีหรือการแทนที่บัญชีที่มีอยู่
หากต้องการให้ผู้ใช้เลือกบัญชีอื่นได้ IdP ต้องระบุฟีเจอร์นี้ ในไฟล์กำหนดค่า
  {
    "accounts_endpoint" : "/accounts.example",
    "supports_use_other_account": true
  }
ปลายทางของบัญชี
ปลายทางบัญชีของ IdP จะแสดงรายการบัญชีที่ผู้ใช้ลงชื่อเข้าใช้ใน IdP หาก IdP รองรับหลายบัญชี ปลายทางนี้จะแสดงบัญชีที่ลงชื่อเข้าใช้ทั้งหมด
เบราว์เซอร์จะส่งคำขอ GET พร้อมคุกกี้ที่มี 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
เมื่อได้รับคำขอ เซิร์ฟเวอร์ควรดำเนินการดังนี้
- ตรวจสอบว่าคำขอมีส่วนหัว Sec-Fetch-Dest: webidentityHTTP
- จับคู่คุกกี้เซสชันกับรหัสของบัญชีที่ลงชื่อเข้าใช้แล้ว
- ตอบกลับพร้อมรายการบัญชี
เบราว์เซอร์คาดหวังว่าจะได้รับการตอบกลับ JSON ที่มีพร็อพเพอร์ตี้ accounts พร้อมอาร์เรย์ข้อมูลบัญชีที่มีพร็อพเพอร์ตี้ต่อไปนี้
| พร็อพเพอร์ตี้ | คำอธิบาย | 
|---|---|
| id(ต้องระบุ) | รหัสที่ไม่ซ้ำกันของผู้ใช้ | 
| name | ชื่อเต็มของผู้ใช้ตามภาษาและค่ากำหนดของผู้ใช้ หมายเหตุ: ตั้งแต่ Chrome 141 เป็นต้นไป จะต้องมีพารามิเตอร์ name,email,usernameหรือtelอย่างน้อย 1 รายการ ใน Chrome เวอร์ชันก่อนหน้า คุณต้องระบุทั้งnameและemail | 
| username | ชื่อผู้ใช้ที่ผู้ใช้เลือก หมายเหตุ: ตั้งแต่ Chrome 141 เป็นต้นไป จะต้องมีพารามิเตอร์ name,email,usernameหรือtelอย่างน้อย 1 รายการ | 
| email | อีเมลของผู้ใช้ หมายเหตุ: ตั้งแต่ Chrome 141 เป็นต้นไป จะต้องมีพารามิเตอร์ name,email,usernameหรือtelอย่างน้อย 1 รายการ ใน Chrome เวอร์ชันก่อนหน้า คุณต้องระบุทั้งnameและemail | 
| tel | หมายเลขโทรศัพท์ของผู้ใช้ หมายเหตุ: ตั้งแต่ Chrome 141 เป็นต้นไป จะต้องมีพารามิเตอร์ name,email,usernameหรือtelอย่างน้อย 1 รายการ | 
| picture(ไม่บังคับ) | URL ของรูปโปรไฟล์ผู้ใช้ | 
| given_name(ไม่บังคับ) | ชื่อของผู้ใช้ | 
| approved_clients(ไม่บังคับ) | อาร์เรย์ของรหัสไคลเอ็นต์ RP ที่ผู้ใช้ลงทะเบียนไว้ | 
| login_hints(ไม่บังคับ) | อาร์เรย์ของประเภทตัวกรองทั้งหมดที่ IdP รองรับเพื่อระบุ
    บัญชี RP สามารถเรียกใช้ navigator.credentials.get()ด้วยพร็อพเพอร์ตี้loginHintเพื่อ
    แสดงบัญชีที่ระบุอย่างเลือกสรร | 
| domain_hints(ไม่บังคับ) | อาร์เรย์ของโดเมนทั้งหมดที่บัญชีเชื่อมโยงอยู่ RP สามารถ
    เรียกใช้ navigator.credentials.get()โดยมีพร็อพเพอร์ตี้domainHintเพื่อกรองบัญชีได้ | 
| label_hints(ไม่บังคับ) | อาร์เรย์ของป้ายกำกับบัญชีที่กำหนดเองแบบสตริงที่บัญชีเชื่อมโยงอยู่ IdP สามารถใช้การติดป้ายกำกับบัญชีที่กำหนดเองได้ดังนี้ 
 ตัวอย่างเช่น IdP จะใช้ https://idp.example/developer-config.jsonไฟล์กำหนดค่าที่มี"account_label": "developer"ที่ระบุ นอกจากนี้ IdP ยังทำเครื่องหมายบัญชีบางบัญชีด้วยป้ายกำกับ"developer"โดยใช้พารามิเตอร์label_hintsใน ปลายทางของบัญชี เมื่อ 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.
      "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 จะใช้ไม่ได้
ปลายทางการยืนยันตัวตน
ปลายทางการยืนยันรหัสของ IdP จะแสดงการยืนยันสำหรับผู้ใช้ที่ลงชื่อเข้าใช้
เมื่อผู้ใช้ลงชื่อเข้าสู่ระบบเว็บไซต์ RP โดยใช้การเรียก navigator.credentials.get()
เบราว์เซอร์จะส่งคำขอ POST พร้อมคุกกี้ที่มี SameSite=None และ
ประเภทเนื้อหา application/x-www-form-urlencoded ไปยังปลายทางนี้พร้อมข้อมูลต่อไปนี้
| พร็อพเพอร์ตี้ | คำอธิบาย | 
|---|---|
| client_id(ต้องระบุ) | ตัวระบุไคลเอ็นต์ของ RP | 
| account_id(ต้องระบุ) | รหัสที่ไม่ซ้ำกันของผู้ใช้ที่ลงชื่อเข้าใช้ | 
| disclosure_text_shown | ผลลัพธ์เป็นสตริงของ "true"หรือ"false"(ไม่ใช่บูลีน) ผลลัพธ์จะเป็น"false"ในกรณีต่อไปนี้
 | 
| disclosure_shown_for | แสดงรายการช่องที่เบราว์เซอร์แสดงต่อผู้ใช้ในข้อความการเปิดเผยข้อมูลเพื่อแจ้งให้ผู้ใช้ทราบว่า RP กำลังขอข้อมูลใดจาก IdP | 
| is_auto_selected | หากมีการตรวจสอบสิทธิ์อีกครั้งโดยอัตโนมัติใน RP is_auto_selectedจะระบุ"true"หรือ"false"ซึ่งจะเป็นประโยชน์ในการรองรับฟีเจอร์ที่เกี่ยวข้องกับการรักษาความปลอดภัยเพิ่มเติม ตัวอย่างเช่น ผู้ใช้บางรายอาจต้องการระดับความปลอดภัยที่สูงขึ้น ซึ่งต้องมีการแทรกแซงจากผู้ใช้โดยชัดแจ้งในการตรวจสอบสิทธิ์ หาก IdP ได้รับคำขอโทเค็นโดยไม่มีการไกล่เกลี่ยดังกล่าว IdP อาจจัดการคำขอแตกต่างออกไป เช่น แสดงรหัสข้อผิดพลาดเพื่อให้ RP เรียกใช้ FedCM API อีกครั้งด้วยmediation: required | 
| fields(ไม่บังคับ) | อาร์เรย์ของสตริงที่ระบุข้อมูลผู้ใช้ที่ RP ขอให้ IdP แชร์ คุณระบุฟิลด์ต่อไปนี้หรือไม่ก็ได้ 
 fields,disclosure_text_shownและdisclosure_shown_forที่แสดงฟิลด์ที่ระบุในคำขอ POST ดังในตัวอย่างต่อไปนี้หมายเหตุ: Chrome 132 ขึ้นไปรองรับ Fields API ฟิลด์ `"username"` และ `"tel"` รองรับตั้งแต่ Chrome 141 | 
| params(ไม่บังคับ) | ออบเจ็กต์ JSON ที่ถูกต้องซึ่งอนุญาตให้ระบุพารามิเตอร์คู่คีย์-ค่าที่กำหนดเองเพิ่มเติม เช่น 
 paramsเป็น JSON แล้วเข้ารหัสเปอร์เซ็นต์หมายเหตุ: Chrome 132 ขึ้นไปรองรับ API พารามิเตอร์ | 
ตัวอย่างส่วนหัว 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¶ms=%22%7B%5C%22nonce%5C%22%3A%5C%22nonce-value%5C%22%7D%22.%0D%0A4&fields=email,picture&disclosure_shown_for=email,picture
เมื่อได้รับคำขอ เซิร์ฟเวอร์ควรดำเนินการดังนี้
- ตอบสนองต่อคำขอด้วย CORS (Cross-Origin Resource Sharing)
- ตรวจสอบว่าคำขอมีส่วนหัว Sec-Fetch-Dest: webidentityHTTP
- จับคู่ส่วนหัว Originกับต้นทาง RP ที่กำหนดโดยclient_idปฏิเสธหากไม่ตรงกัน
- จับคู่ account_idกับรหัสของบัญชีที่ลงชื่อเข้าใช้แล้ว ปฏิเสธ หากไม่ตรงกัน
- ตอบกลับด้วยโทเค็น หากคำขอถูกปฏิเสธ ให้ตอบกลับด้วยการตอบกลับข้อผิดพลาด
IdP สามารถกำหนดวิธีออกโทเค็นได้ โดยทั่วไปแล้ว ระบบจะลงนามด้วย ข้อมูลต่างๆ เช่น รหัสบัญชี รหัสไคลเอ็นต์ ต้นทางของผู้ออก และ Nonce เพื่อให้ RP ยืนยันได้ว่าโทเค็นเป็นของแท้
เบราว์เซอร์คาดหวังการตอบกลับ JSON ที่มีพร็อพเพอร์ตี้ต่อไปนี้
| พร็อพเพอร์ตี้ | คำอธิบาย | 
|---|---|
| token | โทเค็นคือสตริงที่มีการอ้างสิทธิ์เกี่ยวกับการตรวจสอบสิทธิ์ | 
| continue_on | URL เปลี่ยนเส้นทางที่เปิดใช้ขั้นตอนการลงชื่อเข้าใช้แบบหลายขั้นตอน | 
เบราว์เซอร์จะส่งโทเค็นที่ส่งคืนไปยัง RP เพื่อให้ RP สามารถ ตรวจสอบการตรวจสอบสิทธิ์ได้
  {
    // IdP can respond with a token to authenticate the user
    "token": "***********"
  }
ดำเนินการต่อในฟีเจอร์
IdP สามารถระบุ URL เปลี่ยนเส้นทางในคำตอบของปลายทางการยืนยัน ID เพื่อเปิดใช้ขั้นตอนการลงชื่อเข้าใช้แบบหลายขั้นตอน ซึ่งจะเป็นประโยชน์เมื่อ 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 dialog 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 ทำงานร่วมกับโหมดสื่อกลางต่างๆ ดังนี้
- ในpassiveโหมด- mediation: 'optional'(ค่าเริ่มต้น): Continuation API จะทํางานได้ก็ต่อเมื่อ ผู้ใช้ทําท่าทาง เช่น คลิกปุ่มในหน้าเว็บหรือใน UI ของ FedCM เมื่อมีการทริกเกอร์การตรวจสอบสิทธิ์อีกครั้งโดยอัตโนมัติโดยไม่มีท่าทางของผู้ใช้ ระบบจะไม่เปิดหน้าต่างกล่องโต้ตอบและปฏิเสธสัญญา
- mediation: 'required': ขอให้ผู้ใช้โต้ตอบเสมอ ดังนั้น Continuation API จึงใช้งานได้เสมอ
 
- ในโหมดใช้งาน ให้ทำดังนี้
- ต้องเปิดใช้งานผู้ใช้เสมอ Continuation API จะเข้ากันได้เสมอ
 
หากผู้ใช้เปลี่ยนบัญชีในกล่องโต้ตอบด้วยเหตุผลบางประการ (เช่น IdP มีฟังก์ชัน "ใช้บัญชีอื่น" หรือในกรณีการมอบสิทธิ์) การเรียก resolve จะมีอาร์กิวเมนต์ที่ 2 ที่ไม่บังคับซึ่งอนุญาตให้ทำสิ่งต่างๆ เช่น
  IdentityProvider.resolve(token, {accountId: '1234');
แสดงการตอบกลับข้อผิดพลาด
id_assertion_endpoint ยังแสดงผลการตอบกลับ "ข้อผิดพลาด"
 ซึ่งมี 2 ฟิลด์ที่ไม่บังคับได้ด้วย ดังนี้
- code: IdP สามารถเลือกข้อผิดพลาดที่ทราบจากรายการข้อผิดพลาดที่ระบุของ OAuth 2.0 (- invalid_request,- unauthorized_client,- access_denied,- server_errorและ- temporarily_unavailable) หรือใช้สตริงใดก็ได้ หากเป็นกรณีหลัง Chrome จะแสดง UI ข้อผิดพลาดพร้อมข้อความแสดงข้อผิดพลาดทั่วไปและส่งรหัส ไปยัง RP
- url: ระบุหน้าเว็บที่มนุษย์อ่านได้ซึ่งมีข้อมูลเกี่ยวกับข้อผิดพลาดเพื่อให้ข้อมูลเพิ่มเติมเกี่ยวกับข้อผิดพลาดแก่ผู้ใช้ ฟิลด์นี้มีประโยชน์ต่อผู้ใช้เนื่องจากเบราว์เซอร์ไม่สามารถแสดงข้อความแสดงข้อผิดพลาดที่สมบูรณ์ใน UI ในตัวได้ เช่น ลิงก์สำหรับขั้นตอนถัดไปหรือข้อมูลติดต่อของฝ่ายบริการลูกค้า หากผู้ใช้ต้องการดูรายละเอียดข้อผิดพลาดเพิ่มเติม และวิธีแก้ไข ผู้ใช้สามารถไปที่หน้าที่ระบุจาก UI ของเบราว์เซอร์ เพื่อดูรายละเอียดเพิ่มเติมได้ 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"
คุณสามารถกรองในลักษณะเดียวกันได้โดยใช้ฟีเจอร์คำใบ้โดเมน
และคำใบ้การเข้าสู่ระบบ
โดยระบุฟีเจอร์ดังกล่าวในการเรียกใช้ navigator.credentials.get() อย่างไรก็ตาม
ป้ายกำกับบัญชีที่กำหนดเองสามารถกรองผู้ใช้ได้โดยการระบุไฟล์กำหนดค่า ซึ่งมีประโยชน์อย่างยิ่งเมื่อใช้ configURL หลายรายการ ป้ายกำกับบัญชีที่กำหนดเองยังแตกต่างกันตรงที่มาจากเซิร์ฟเวอร์ IdP
ซึ่งต่างจาก RP เช่น คำแนะนำในการเข้าสู่ระบบหรือโดเมน
พิจารณา IdP ที่ต้องการแยกความแตกต่างระหว่างบัญชี "developer" กับ "hr"
 หากต้องการดำเนินการนี้ IdP ต้องรองรับ ConfigURL 2 รายการสำหรับ
"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"
  }
- เมื่อตั้งค่าดังกล่าว ไฟล์ที่รู้จักกันดีควรมี
accounts_endpointและlogin_urlเพื่ออนุญาตให้มี configURL หลายรายการ
  {
    "provider_urls": [ "https://idp.example/fedcm.json" ],
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }
- ปลายทางบัญชี IdP ทั่วไป (ในตัวอย่างนี้คือ
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"]
    }]
  }
เมื่อ RP ต้องการอนุญาตให้"hr"ผู้ใช้ลงชื่อเข้าใช้ RP จะระบุ
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 ไม่รองรับในเว็บไซต์นี้
ข้อควรพิจารณาเพิ่มเติม
- ป้ายกำกับเป็นสตริง หากอาร์เรย์ label_hintsหรือฟิลด์account_labelใช้ค่าที่ไม่ใช่สตริง ระบบจะไม่สนใจค่าดังกล่าว
- หากไม่ได้ระบุป้ายกำกับใน configURLระบบจะแสดงบัญชีทั้งหมดในเครื่องมือเลือกบัญชี FedCM
- หากไม่ได้ระบุป้ายกำกับสำหรับบัญชี บัญชีนี้จะแสดงในตัวเลือกบัญชีก็ต่อเมื่อ configURLไม่ได้ระบุป้ายกำกับด้วยเช่นกัน
- หากไม่มีบัญชีที่ตรงกับป้ายกำกับที่ขอในโหมดพาสซีฟ (คล้ายกับ ฟีเจอร์คำแนะนำโดเมน) กล่องโต้ตอบ FedCM จะแสดงข้อความแจ้งให้เข้าสู่ระบบ ซึ่งช่วยให้ ผู้ใช้ลงชื่อเข้าใช้บัญชี IdP ได้ สำหรับโหมดที่ใช้งานอยู่ ระบบจะเปิดกล่องโต้ตอบการเข้าสู่ระบบ โดยตรง
ยกเลิกการเชื่อมต่ออุปกรณ์ปลายทาง
เมื่อเรียกใช้ IdentityCredential.disconnect() เบราว์เซอร์จะส่งคำขอข้ามต้นทาง
POSTพร้อมคุกกี้ที่มี 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
เมื่อได้รับคำขอ เซิร์ฟเวอร์ควรดำเนินการดังนี้
- ตอบสนองต่อคำขอด้วย CORS (Cross-Origin Resource Sharing)
- ตรวจสอบว่าคำขอมีส่วนหัว Sec-Fetch-Dest: webidentityHTTP
- จับคู่ส่วนหัว Originกับต้นทาง RP ที่กำหนดโดยclient_idปฏิเสธหากไม่ตรงกัน
- จับคู่ account_hintกับรหัสของบัญชีที่ลงชื่อเข้าใช้แล้ว
- ยกเลิกการเชื่อมต่อบัญชีผู้ใช้จาก RP
- ตอบกลับเบราว์เซอร์ด้วยข้อมูลบัญชีผู้ใช้ที่ระบุใน รูปแบบ JSON
เพย์โหลด JSON ของการตอบกลับตัวอย่างมีลักษณะดังนี้
  {
    "account_id": "account456"
  }
แต่หาก IdP ต้องการให้เบราว์เซอร์ยกเลิกการเชื่อมต่อบัญชีทั้งหมดที่เชื่อมโยงกับ RP ให้ส่งสตริงที่ไม่ตรงกับรหัสบัญชีใดๆ เช่น "*"
ปลายทางข้อมูลเมตาของไคลเอ็นต์
ปลายทางข้อมูลเมตาของไคลเอ็นต์ IdP จะแสดงข้อมูลเมตาของ Relying Party เช่น นโยบายความเป็นส่วนตัว ข้อกำหนดในการให้บริการ และไอคอนโลโก้ของ RP RP ควรระบุลิงก์ไปยังนโยบายความเป็นส่วนตัวและข้อกำหนดในการให้บริการของตนให้ IdP ทราบล่วงหน้า ลิงก์เหล่านี้จะแสดงในกล่องโต้ตอบการลงชื่อเข้าใช้เมื่อผู้ใช้ยังไม่ได้ลงทะเบียนใน RP ด้วย IdP
เบราว์เซอร์จะส่งคำขอ GET โดยใช้ client_id
navigator.credentials.get โดยไม่มีคุกกี้ เช่น
  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
เมื่อได้รับคำขอ เซิร์ฟเวอร์ควรดำเนินการดังนี้
- กำหนด RP สำหรับ client_id
- ตอบกลับด้วยข้อมูลเมตาของไคลเอ็นต์
พร็อพเพอร์ตี้สำหรับปลายทางข้อมูลเมตาของไคลเอ็นต์มีดังนี้
| พร็อพเพอร์ตี้ | คำอธิบาย | 
|---|---|
| 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 ของหน้าเข้าสู่ระบบที่ระบุไว้ใน idp config file ของ login_url ได้แบบไดนามิก
กล่องโต้ตอบ FedCM จะแสดงข้อความที่แนะนำให้ลงชื่อเข้าใช้ ดังที่แสดงใน รูปภาพต่อไปนี้
 
   เมื่อผู้ใช้คลิกปุ่มต่อไป เบราว์เซอร์จะเปิดหน้าต่างกล่องโต้ตอบ สำหรับหน้าเข้าสู่ระบบของ IdP
 
   กล่องโต้ตอบคือหน้าต่างเบราว์เซอร์ปกติที่มีคุกกี้ของบุคคลที่หนึ่ง ไม่ว่าจะเกิดอะไรขึ้นภายในกล่องโต้ตอบก็ขึ้นอยู่กับ IdP และไม่มีแฮนเดิลหน้าต่างที่จะส่งคำขอการสื่อสารข้ามต้นทางไปยังหน้า RP หลังจากผู้ใช้ ลงชื่อเข้าใช้แล้ว IdP ควรทำดังนี้
- ส่งส่วนหัว Set-Login: logged-inหรือเรียกใช้ APInavigator.login.setStatus("logged-in")เพื่อแจ้งให้เบราว์เซอร์ทราบว่าผู้ใช้ได้ลงชื่อเข้าใช้แล้ว
- โทร IdentityProvider.close()เพื่อปิดกล่องโต้ตอบ
แจ้งสถานะการเข้าสู่ระบบของผู้ใช้ให้เบราว์เซอร์ทราบ
Login Status API เป็นกลไก ที่เว็บไซต์ โดยเฉพาะ IdP จะแจ้งสถานะการเข้าสู่ระบบของผู้ใช้ใน IdP ให้เบราว์เซอร์ทราบ API นี้ช่วยให้เบราว์เซอร์ลดคำขอที่ไม่จำเป็นไปยัง IdP และลดการโจมตีที่อาจเกิดขึ้นตามเวลา
IdP สามารถส่งสัญญาณสถานะการเข้าสู่ระบบของผู้ใช้ไปยังเบราว์เซอร์ได้โดยการส่งส่วนหัว HTTP หรือโดยการเรียกใช้ JavaScript API เมื่อผู้ใช้ลงชื่อเข้าใช้ใน IdP หรือเมื่อ ผู้ใช้ลงชื่อออกจากบัญชี IdP ทั้งหมด สำหรับ IdP แต่ละรายการ (ระบุโดย URL การกำหนดค่า) เบราว์เซอร์จะเก็บตัวแปรแบบ 3 สถานะที่แสดงสถานะการเข้าสู่ระบบ โดยมีค่าที่เป็นไปได้ดังนี้
- logged-in
- logged-out
- unknown(ค่าเริ่มต้น)
| สถานะการเข้าสู่ระบบ | คำอธิบาย | 
|---|---|
| logged-in | เมื่อตั้งค่าสถานะการเข้าสู่ระบบของผู้ใช้เป็น logged-inRP ที่เรียกใช้ FedCM จะส่งคำขอไปยังปลายทางบัญชีของ IdP และแสดงบัญชีที่พร้อมใช้งานต่อผู้ใช้ในกล่องโต้ตอบ FedCM | 
| logged-out | เมื่อสถานะการเข้าสู่ระบบของผู้ใช้เป็น logged-outการเรียกใช้ FedCM จะล้มเหลวโดยไม่มีการแจ้งเตือนโดยไม่ต้องส่งคำขอไปยังปลายทางบัญชีของ IdP | 
| unknown(ค่าเริ่มต้น) | ระบบจะตั้งค่าสถานะ unknownก่อนที่ IdP จะส่งสัญญาณโดยใช้ Login Status API เมื่อสถานะเป็นunknownเบราว์เซอร์จะส่งคำขอไปยังปลายทางบัญชีของ IdP และอัปเดตสถานะตามการตอบกลับจากปลายทางบัญชี | 
หากต้องการส่งสัญญาณว่าผู้ใช้ลงชื่อเข้าใช้แล้ว ให้ส่งSet-Login: logged-inส่วนหัว HTTP
ในการนำทางระดับบนสุดหรือคำขอทรัพยากรย่อยแบบเดียวกันที่ต้นทาง IdP โดยทำดังนี้
  Set-Login: logged-in
หรือจะเรียกใช้เมธอด JavaScript navigator.login.setStatus('logged-in') จากต้นทาง IdP ในการนำทางระดับบนสุด
ก็ได้
  navigator.login.setStatus('logged-in')
ระบบจะตั้งค่าสถานะการเข้าสู่ระบบของผู้ใช้เป็น logged-in
หากต้องการส่งสัญญาณว่าผู้ใช้ได้ออกจากระบบบัญชีทั้งหมดแล้ว ให้ส่งSet-Login: logged-outส่วนหัว HTTP ในการนำทางระดับบนสุดหรือคำขอทรัพยากรย่อยแบบเดียวกันที่ต้นทาง 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 ผ่านหน้าต่างกล่องโต้ตอบแบบไดนามิกได้