ID プロバイダ側で FedCM を使用して ID ソリューションを実装する

FedCM の実装には、ID プロバイダ(IdP)リライング パーティ(RP)の両方に対するいくつかのコアステップが含まれます。RP 側で FedCM を実装する方法については、ドキュメントをご覧ください。

IdPs は、FedCM を実装するために次の手順を完了する必要があります。

.well-known ファイルを作成する

トラッカーによる API の不正使用を防ぐため、IdP の eTLD+1/.well-known/web-identity から well-known ファイルを提供する必要があります。

既知のファイルには次のプロパティを含めることができます。

プロパティ 必須 説明
provider_urls 必須 IdP 構成ファイルのパスの配列。accounts_endpointlogin_url が指定されている場合は無視されます(ただし、必須です)。
accounts_endpoint 推奨、login_url
が必要
アカウント エンドポイントの URL。これにより、各構成ファイルが同じ login_urlaccounts_endpoint の URL を使用している限り、複数の構成をサポートできます。

注: このパラメータは Chrome 132 以降でサポートされています。
login_url 推奨、accounts_endpoint が必要 ユーザーが IdP にログインするためのログインページの URL。これにより、各構成ファイルが同じ login_urlaccounts_endpoint を使用している限り、複数の構成をサポートできます。

注: このパラメータは Chrome 132 以降でサポートされています。

たとえば、IdP エンドポイントが https://accounts.idp.example/ で提供されている場合、https://idp.example/.well-known/web-identity で既知のファイルと IdP 構成ファイルも提供する必要があります。以下は、well-known ファイルのコンテンツの例です。

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

IdP は、well-known ファイルで accounts_endpointlogin_url を指定することで、IdP の複数の構成ファイルに対応できます。この機能は、次のような場合に役立ちます。

  • IdP は、さまざまなテスト構成と本番環境構成をサポートする必要があります。
  • IdP は、リージョンごとに異なる構成(eu-idp.exampleus-idp.example など)をサポートする必要があります。

複数の構成をサポートするには(たとえば、テスト環境と本番環境を区別するため)、IdP は accounts_endpointlogin_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 コンテンツ タイプで提供する必要があります。

構成ファイルの URL は、RP で実行される navigator.credentials.get() 呼び出しに提供される値によって決まります。RP は、すべての ID プロバイダの構成ファイルの 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
  }

ブラウザは、Origin ヘッダーまたは Referer ヘッダーのない GET リクエストで構成ファイルを取得します。リクエストに 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。
account_label(省略可) カスタム アカウント ラベル文字列。この構成ファイルが使用されたときに返されるアカウントを決定します(例: "account_label": "developer")。
IdP は、次のようにカスタム アカウント ラベリングを実装できます。

たとえば、IdP は "account_label": "developer" を指定して "https://idp.example/developer-config.json" 構成ファイルを実装します。IdP は、アカウント エンドポイントlabel_hints パラメータを使用して、一部のアカウントに "developer" ラベルを付けます。RP が "https://idp.example/developer-config.json" 構成ファイルを指定して navigator.credentials.get() を呼び出すと、"developer" ラベルの付いたアカウントのみが返されます。

注: カスタム アカウント ラベルは Chrome 132 以降でサポートされています。
supports_use_other_account(任意) ユーザーが現在ログインしているアカウントとは異なるアカウントでログインできるかどうかを指定するブール値(IdP が複数のアカウントをサポートしている場合)。これはアクティブ モードにのみ適用されます。
client_metadata_endpoint(任意) クライアント メタデータ エンドポイントの URL。
id_assertion_endpoint(必須) ID アサーション エンドポイントの URL。
disconnect(任意) 切断エンドポイントの URL。
login_url(必須) ユーザーが IdP にログインするためのログインページの URL
branding(任意) さまざまなブランディング オプションを含むオブジェクト。
branding.background_color(任意) 「Continue as...」ボタンの背景色を設定するブランディング オプション。関連する CSS 構文(hex-colorhsl()rgb()named-color)を使用します。
branding.color(任意) 「...として続行」ボタンのテキストの色を設定するブランディング オプション。関連する CSS 構文(hex-colorhsl()rgb()named-color)を使用します。
branding.icons(任意) アイコン オブジェクトの配列。これらのアイコンはログイン ダイアログに表示されます。アイコン オブジェクトには次の 2 つのパラメータがあります。
  • url(必須): アイコン画像の URL。SVG 画像はサポートされていません。
  • size(省略可): アイコンの寸法。アプリケーションでは正方形で単一の解像度であると想定されます。この数値は、パッシブ モードでは 25 ピクセル以上、アクティブ モードでは 40 ピクセル以上である必要があります。

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 エンドポイント

別のアカウントを使用

IdP が複数のアカウントをサポートしている場合や、既存のアカウントの置き換えをサポートしている場合は、現在ログインしているアカウントとは別のアカウントに切り替えることができます。

ユーザーが他のアカウントを選択できるようにするには、IdP が構成ファイルでこの機能を指定する必要があります。

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

アカウント エンドポイント

IdP のアカウント エンドポイントは、ユーザーが IdP にログインしているアカウントのリストを返します。IdP が複数のアカウントをサポートしている場合、このエンドポイントはログインしているすべてのアカウントを返します。

ブラウザは、SameSite=None を含む Cookie を使用して GET リクエストを送信しますが、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. リクエストに Sec-Fetch-Dest: webidentity HTTP ヘッダーが含まれていることを確認します。
  2. セッション Cookie を、すでにログインしているアカウントの ID と照合します。
  3. アカウントのリストを返します。

ブラウザは、次のプロパティを含むアカウント情報の配列を持つ accounts プロパティを含む JSON レスポンスを想定しています。

プロパティ 説明
id(必須) ユーザーの一意の ID。
name ユーザーのロケールと設定に基づくユーザーの氏名。

注: Chrome 141 以降では、nameemailusernametel のいずれかのパラメータが少なくとも 1 つ必要です。以前の Chrome バージョンでは、nameemail の両方が必要です。
username ユーザーが選択したユーザー名。

注: Chrome 141 以降では、nameemailusernametel のいずれかのパラメータが少なくとも 1 つ必要です。
email ユーザーのメールアドレス。

注: Chrome 141 以降では、nameemailusernametel のいずれかのパラメータが少なくとも 1 つ必要です。以前の Chrome バージョンでは、nameemail の両方が必要です。
tel ユーザーの電話番号。

注: Chrome 141 以降では、nameemailusernametel のいずれかのパラメータが少なくとも 1 つ必要です。
picture(任意) ユーザーのアバター画像の URL。
given_name(任意) ユーザーの名。
approved_clients(任意) ユーザーが登録した RP クライアント ID の配列。
login_hints(任意) IdP がアカウントの指定をサポートするすべてのフィルタタイプの配列。RP は loginHint プロパティを指定して navigator.credentials.get() を呼び出し、指定したアカウントを選択的に表示できます。
domain_hints(任意) アカウントに関連付けられているすべてのドメインの配列。RP は、domainHint プロパティを指定して navigator.credentials.get() を呼び出し、アカウントをフィルタできます。
label_hints(省略可) アカウントに関連付けられている文字列のカスタム アカウント ラベルの配列。
IdP は、次のようにカスタム アカウント ラベリングを実装できます。
  • アカウント エンドポイントでアカウント ラベルを指定します(この label_hints パラメータを使用)。
  • 特定のラベルごとに構成ファイルを作成します。

たとえば、IdP は "account_label": "developer" を指定して https://idp.example/developer-config.json 構成ファイルを実装します。IdP は、 アカウント エンドポイントlabel_hints パラメータを使用して、一部のアカウントに "developer" ラベルを付けます。RP が https://idp.example/developer-config.json 構成ファイルを指定して navigator.credentials.get() を呼び出すと、"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(Unauthorized)で応答します。

返されたアカウント リストはブラウザによって使用され、RP では利用できません。

ID アサーション エンドポイント

IdP の ID アサーション エンドポイントは、ログインしているユーザーのアサーションを返します。ユーザーが navigator.credentials.get() 呼び出しを使用して RP ウェブサイトにログインすると、ブラウザは SameSite=None を含む Cookie と application/x-www-form-urlencoded のコンテンツ タイプを含む POST リクエストを、次の情報とともにこのエンドポイントに送信します。

プロパティ 説明
client_id(必須) RP のクライアント識別子。
account_id(必須) ログインしているユーザーの一意の ID。
disclosure_text_shown 結果はブール値ではなく、"true" または "false" の文字列になります。次の場合は、結果は "false" になります。
  • RP のクライアント ID が アカウント エンドポイントからのレスポンスの approved_clients プロパティ リストに含まれていたために開示テキストが表示されなかった場合。
  • ブラウザが過去に approved_clients がない状態で登録のタイミングを検出したため、開示テキストが表示されなかった場合。
  • fields パラメータに 3 つのフィールド(「name」、「email」、「picture」)のすべてが含まれていない場合(例: fields=[ ]fields=['name', 'picture'])。これは、古い実装との下位互換性を維持するために必要です。

    注: Chrome 141 以降では、disclosure_text_shown の値が "false" であっても、開示テキストが表示されることがあります。開示テキストが表示されたかどうかを確認するには、代わりに disclosure_shown_for の値を確認します。
disclosure_shown_for 開示テキストでブラウザがユーザーに表示したフィールドを一覧表示し、RP が IdP にリクエストしているデータをユーザーに通知します。
is_auto_selected RP で自動再認証が行われた場合、is_auto_selected"true" を示します。それ以外の場合は "false"。これは、セキュリティ関連の機能をサポートするうえで役立ちます。たとえば、認証でユーザーの明示的な仲介を必要とする、より高いセキュリティ階層を好むユーザーもいます。IdP がこのようなメディエーションなしでトークン リクエストを受信した場合、リクエストの処理方法が異なる可能性があります。たとえば、RP が mediation: required を使用して FedCM API を再度呼び出すことができるように、エラーコードを返します。
fields(省略可) RP が IdP に共有をリクエストしたユーザー情報を指定する文字列の配列。次のフィールドは必要に応じて指定できます。
  • "name"
  • "username"
  • "email"
  • "tel"
  • "picture"
ブラウザは、次の例のように、POST リクエストで指定されたフィールドをリストする fieldsdisclosure_text_showndisclosure_shown_for を送信します。

注: Fields API は Chrome 132 以降でサポートされています。`"username"` フィールドと `"tel"` フィールドは Chrome 141 以降でサポートされています。
params(省略可) 追加のカスタム Key-Value パラメータを指定できる有効な JSON オブジェクト(例:
  • scope: RP がリクエストする必要がある追加の権限を含む文字列値(例: "drive.readonly calendar.readonly"
  • nonce: レスポンスがこの特定のリクエストに対して発行されるように RP が提供するランダムな文字列。リプレイ攻撃を防ぎます。
  • その他のカスタム Key-Value パラメータ。
ブラウザが POST リクエストを送信すると、params 値は JSON にシリアル化され、パーセント エンコードされます。

注: パラメータ API は Chrome 132 以降でサポートされています。

HTTP ヘッダーの例:

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

  // disclosure_text_shown is set to 'false', as the 'name' field value is missing in 'fields' array
  // params value is serialized to JSON and then percent-encoded.
  account_id=123&client_id=client1234&disclosure_text_shown=false&is_auto_selected=true&params=%22%7B%5C%22nonce%5C%22%3A%5C%22nonce-value%5C%22%7D%22.%0D%0A4&fields=email,picture&disclosure_shown_for=email,picture

リクエストを受け取ったサーバーは、次の処理を行う必要があります。

  1. CORS(クロスオリジン リソース シェアリング)でリクエストに応答します。
  2. リクエストに Sec-Fetch-Dest: webidentity HTTP ヘッダーが含まれていることを確認します。
  3. client_id によって決定された RP オリジンに対して Origin ヘッダーを照合します。一致しない場合は不承認にします。
  4. account_id を、すでにログインしているアカウントの ID と照合します。一致しない場合は拒否します。
  5. トークンで応答します。リクエストが拒否された場合は、エラー レスポンスで応答します。

IdP は、トークンの発行方法を決定できます。通常、アカウント ID、クライアント ID、発行者のオリジン、ノンスなどの情報で署名され、RP がトークンが本物であることを確認できるようになっています。

ブラウザは、次のプロパティを含む JSON レスポンスを想定しています。

プロパティ 説明
token トークンは、認証に関するクレームを含む文字列です。
continue_on 複数ステップのログインフローを有効にするリダイレクト URL。

返されたトークンはブラウザによって RP に渡され、RP は認証を検証できます。

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

機能で続行

IdP は、ID アサーション エンドポイントのレスポンスでリダイレクト URL を提供して、複数ステップのログインフローを有効にできます。これは、IdP が追加の情報や権限をリクエストする必要がある場合に便利です。たとえば、次のような場合です。

  • ユーザーのサーバーサイド リソースにアクセスする権限。
  • 連絡先情報が最新であることを確認します。
  • 保護者による使用制限。

ID アサーション エンドポイントは、ID アサーション エンドポイントの絶対パスまたは相対パスを含む 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 は、元の navigator.credentials.get() 呼び出しからの Promise を解決できるように、引数として渡されたトークンを使用して IdentityProvider.resolve() を呼び出す必要があります。

  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 呼び出し元にトークンを返します。1 回限りの IdentityProvider.resolve() 呼び出しは、親ウィンドウ(RP)とポップアップ ウィンドウ(IdP)が通信する唯一の方法です。
ユーザーがリクエストを拒否した場合、IdP は IdentityProvider.close() を呼び出してウィンドウを閉じることができます。

  IdentityProvider.close();

継続 API は、機能するためにユーザーの明示的な操作(クリック)を必要とします。Continuation API は、さまざまなメディエーション モードで次のように動作します。

  • passive モードの場合:
    • mediation: 'optional'(デフォルト): Continuation API は、ページまたは FedCM UI のボタンをクリックするなどのユーザー操作でのみ機能します。ユーザー操作なしで自動再認証がトリガーされた場合、ポップアップ ウィンドウは開かれず、Promise は拒否されます。
    • mediation: 'required': 常にユーザーに操作を求めるため、Continuation API は常に機能します。
  • アクティブ モードの場合:
    • ユーザーの有効化は常に必要です。継続 API は常に互換性があります。

ユーザーがポップアップでアカウントを変更した場合(IdP が「別のアカウントを使用」機能を提供している場合や、委任の場合など)、resolve 呼び出しはオプションの 2 番目の引数を取り、次のような処理を可能にします。

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

エラー レスポンスを返す

id_assertion_endpoint は、2 つのオプション フィールドを含む「エラー」レスポンスを返すこともできます。

  • code: IdP は、OAuth 2.0 で指定されたエラーリストinvalid_requestunauthorized_clientaccess_deniedserver_errortemporarily_unavailable)から既知のエラーを 1 つ選択するか、任意の文字列を使用できます。後者の場合、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() 呼び出しで Domain Hint 機能と Login Hint 機能を指定することでも可能です。ただし、カスタム アカウント ラベルでは、構成ファイルを指定してユーザーをフィルタできます。これは、複数の configURL が使用されている場合に特に便利です。カスタム アカウント ラベルは、ログインやドメインのヒントのように RP から提供されるのではなく、IdP サーバーから提供されるという点でも異なります。

"developer" アカウントと "hr" アカウントを区別したい IdP を考えてみましょう。これを実現するには、IdP が "developer""hr" の 2 つの configURL をそれぞれサポートする必要があります。

  • デベロッパー構成ファイル 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"
  }
  • このような設定では、複数の configURL を許可するために、well-known ファイルaccounts_endpointlogin_url を含める必要があります。
  {
    "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" ユーザーのログインを許可する場合は、navigator.credentials.get() 呼び出しで configURL https://idp.example/hr/fedcm.json を指定できます。

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

その結果、ユーザーがログインに使用できるのは 4567 のアカウント ID のみになります。123 のアカウント ID はブラウザによって非表示にされるため、ユーザーにはこのサイトの IdP でサポートされていないアカウントは提供されません。

その他の考慮事項:

  • ラベルは文字列です。label_hints 配列または account_label フィールドで文字列以外の値が使用されている場合、その値は無視されます。
  • configURL でラベルが指定されていない場合、すべてのユーザー アカウントが FedCM アカウント選択ツールに表示されます。
  • アカウントにラベルが指定されていない場合、このアカウントは configURL でもラベルが指定されていない場合にのみ、アカウント選択ツールに表示されます。
  • パッシブ モードでリクエストされたラベルに一致するアカウントがない場合(ドメイン ヒント機能と同様)、FedCM ダイアログにログイン プロンプトが表示され、ユーザーは IdP アカウントにログインできます。アクティブ モードでは、ログイン ポップアップ ウィンドウが直接開きます。

エンドポイントを切断する

IdentityCredential.disconnect() を呼び出すと、ブラウザは SameSite=Noneapplication/x-www-form-urlencoded のコンテンツ タイプを含む Cookie を使用して、クロスオリジン POST リクエストを次の情報とともにこの切断エンドポイントに送信します。

プロパティ 説明
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. リクエストに Sec-Fetch-Dest: webidentity HTTP ヘッダーが含まれていることを確認します。
  3. client_id によって決定された RP オリジンに対して Origin ヘッダーを照合します。一致しない場合は不承認にします。
  4. account_hint を、すでにログインしているアカウントの ID と照合します。
  5. ユーザー アカウントと RP の接続を解除します。
  6. 特定されたユーザー アカウント情報を JSON 形式でブラウザに返します。

レスポンスの JSON ペイロードの例は次のようになります。

  {
    "account_id": "account456"
  }

代わりに、IdP が RP に関連付けられているすべてのアカウントの接続をブラウザに解除させたい場合は、アカウント ID と一致しない文字列("*" など)を渡します。

クライアント メタデータ エンドポイント

IdP のクライアント メタデータ エンドポイントは、RP のプライバシー ポリシー、利用規約、ロゴアイコンなどの RP のメタデータを返します。RP は、プライバシー ポリシーと利用規約へのリンクを事前に IdP に提供する必要があります。これらのリンクは、ユーザーが IdP で RP にまだ登録していない場合に、ログイン ダイアログに表示されます。

ブラウザは、Cookie なしで client_id navigator.credentials.get を使用して 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

リクエストを受け取ったサーバーは、次の処理を行う必要があります。

  1. client_id の RP を決定します。
  2. クライアント メタデータで応答します。

クライアント メタデータ エンドポイントのプロパティは次のとおりです。

プロパティ 説明
privacy_policy_url(任意) RP のプライバシー ポリシーの URL。
terms_of_service_url(任意) RP の利用規約の URL。
icons(任意) [{ "url": "https://rp.example/rp-icon.ico", "size": 40}] などのオブジェクトの配列

ブラウザはエンドポイントから JSON レスポンスを受け取ることを想定しています。

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

返されたクライアント メタデータはブラウザによって使用され、RP で利用することはできません。

ログイン URL

このエンドポイントは、ユーザーが IdP にログインできるようにするために使用されます。

Login Status API を使用して、IdP はユーザーのログイン ステータスをブラウザに通知する必要があります。ただし、セッションの有効期限が切れた場合など、ステータスが同期されていない可能性があります。このようなシナリオでは、ブラウザは IdP 構成ファイルlogin_url で指定されたログイン ページの URL を介して、ユーザーが IdP に動的にログインできるようにします。

次の画像に示すように、FedCM ダイアログにログインを促すメッセージが表示されます。

IdP へのログインを促す FedCM ダイアログ。
IdP へのログインを提案する FedCM ダイアログ。

ユーザーが [続行] ボタンをクリックすると、ブラウザで IdP のログインページのポップアップ ウィンドウが開きます。

FedCM ダイアログの例。
IdP にログイン ボタンをクリックした後に表示されるダイアログの例。

このダイアログは、ファーストパーティ Cookie を含む通常のブラウザ ウィンドウです。ダイアログ内で発生する処理は IdP に依存し、RP ページにクロスオリジン通信リクエストを行うためのウィンドウ ハンドルは使用できません。ユーザーがログインした後、IdP は次の処理を行う必要があります。

  • Set-Login: logged-in ヘッダーを送信するか、navigator.login.setStatus("logged-in") API を呼び出して、ユーザーがログインしたことをブラウザに通知します。
  • IdentityProvider.close() を呼び出してダイアログを閉じます。
ユーザーは、FedCM を使用して IdP にログインした後、RP にログインします。

ユーザーのログイン ステータスをブラウザに通知する

ログイン ステータス API は、ウェブサイト(特に IdP)がブラウザに IdP でのユーザーのログイン ステータスを通知するメカニズムです。この API を使用すると、ブラウザは IdP への不要なリクエストを減らし、タイミング攻撃の可能性を軽減できます。

IdP は、ユーザーが IdP にログインしたとき、またはすべての IdP アカウントからログアウトしたときに、HTTP ヘッダーを送信するか JavaScript API を呼び出すことで、ユーザーのログイン ステータスをブラウザに通知できます。ブラウザは、各 IdP(構成 URL で識別)について、ログイン状態を表す 3 状態の変数を保持します。この変数の値は次のいずれかになります。

  • logged-in
  • logged-out
  • unknown(デフォルト)
ログイン ステータス 説明
logged-in ユーザーのログイン ステータスが logged-in に設定されている場合、FedCM を呼び出す RP は IdP のアカウント エンドポイントにリクエストを行い、利用可能なアカウントを FedCM ダイアログに表示します。
logged-out ユーザーのログイン ステータスが logged-out の場合、IdP のアカウント エンドポイントにリクエストを送信することなく、FedCM はサイレントに失敗します。
unknown(デフォルト) unknown ステータスは、IdP がログイン ステータス API を使用してシグナルを送信する前に設定されます。ステータスが unknown の場合、ブラウザは IdP のアカウント エンドポイントにリクエストを行い、アカウント エンドポイントからのレスポンスに基づいてステータスを更新します。

ユーザーがログインしていることを示すには、IdP オリジンでトップレベル ナビゲーションまたは同一サイト サブリソース リクエストで Set-Login: logged-in HTTP ヘッダーを送信します。

  Set-Login: logged-in

または、トップレベル ナビゲーションで IdP オリジンから JavaScript メソッド navigator.login.setStatus('logged-in') を呼び出します。

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

ユーザーのログイン ステータスが logged-in に設定されます。

ユーザーがすべてのアカウントからログアウトしたことを通知するには、IdP オリジンで最上位ナビゲーションまたは同一サイトのサブリソース リクエストで Set-Login: logged-out HTTP ヘッダーを送信します。

  Set-Login: logged-out

または、最上位のナビゲーションで IdP オリジンから JavaScript API navigator.login.setStatus('logged-out') を呼び出します。

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

ユーザーのログイン ステータスが logged-out に設定されます。

unknown ステータスは、IdP がログイン ステータス API を使用してシグナルを送信する前に設定されます。ブラウザは IdP のアカウント エンドポイントにリクエストを行い、アカウント エンドポイントからのレスポンスに基づいてステータスを更新します。

  • エンドポイントが有効なアカウントのリストを返した場合は、ステータスを logged-in に更新し、FedCM ダイアログを開いてそれらのアカウントを表示します。
  • エンドポイントがアカウントを返さない場合は、ステータスを logged-out に更新し、FedCM 呼び出しを失敗させます。

動的ログインフローでユーザーがログインできるようにする

IdP はユーザーのログイン ステータスをブラウザに通知し続けますが、セッションの有効期限が切れた場合など、同期が取れなくなる可能性があります。ログイン ステータスが logged-in の場合、ブラウザは認証情報付きのリクエストをアカウント エンドポイントに送信しようとしますが、セッションが利用できなくなったため、サーバーはアカウントを返しません。このようなシナリオでは、ブラウザはポップアップ ウィンドウを通じてユーザーが IdP に動的にログインできるようにします

次のステップ

RP に FedCM を実装し、JavaScript SDK を配布します。セルフ実装の必要がないため、RP を最新の状態に保つことができます。
環境を設定し、実装をデバッグする方法を学びます。