FedCM の更新: Login Status API、Error API、Auto-selected Flag API

Chrome 120 では、FedCM 用にログイン ステータス API が提供されています。 Login Status API(旧称 IdP Sign-in Status API)を使用すると、ウェブサイト(特に ID プロバイダ)はユーザーがログインまたはログアウトしているときにブラウザにシグナルを送信できます。このシグナルは、サイレント タイミング攻撃の問題に対処するために FedCM によって使用されます。これにより、FedCM はサードパーティ Cookie なしで動作できるようになります。今回のアップデートでは、作業範囲の一部として、FedCM の出荷に関する最初の意図で以前に特定された、下位互換性のない残りの変更に対処しています。

Login Status API はプライバシーのプロパティとユーザビリティを向上させますが、リリース後は下位互換性のない変更となります。FedCM の既存の実装がある場合は、次の手順でアップデートしてください。

さらに、Chrome には 2 つの新しいフェデレーション認証情報管理(FedCM)機能が搭載されています。

  • Error API: ログイン試行が失敗した場合、ID アサーション エンドポイントからのサーバー応答に基づいてネイティブ UI でユーザーに通知します(存在する場合)。
  • Auto-Selected Flag API: フローで認証情報が自動的に選択された場合に、ID プロバイダ(IdP)と証明書利用者(RP)に通知します。

Login Status API

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

ユーザーのログイン ステータスをブラウザに伝える

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

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

Set-Login: logged-in

または、IdP オリジンから JavaScript API navigator.login.setStatus('logged-in') を呼び出します。

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

これらの呼び出しは、ユーザーのログイン ステータスを logged-in として記録します。ユーザーのログイン ステータスが logged-in に設定されている場合、FedCM を呼び出している RP が IdP のアカウント リスト エンドポイントにリクエストを行い、利用可能なアカウントを FedCM ダイアログに表示します。

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

Set-Login: logged-out

または、IdP オリジンから JavaScript API navigator.login.setStatus('logged-out') を呼び出します。

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

これらの呼び出しは、ユーザーのログイン ステータスを logged-out として記録します。ユーザーのログイン ステータスが logged-out の場合、FedCM の呼び出しは IdP のアカウント リスト エンドポイントにリクエストを行うことなく、通知なく失敗します。

unknown ステータスは、IdP が Login Status API を使用してシグナルを送信する前に設定されます。このステータスは、この API の出荷時にユーザーがすでに IdP にログインしているため、移行を改善するために導入されています。FedCM が最初に呼び出されるまでに、IdP がブラウザにこれを通知できない可能性があります。この場合、IdP のアカウント リスト エンドポイントにリクエストを行い、アカウント リスト エンドポイントからのレスポンスに基づいてステータスを更新します。

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

ユーザー セッションの有効期限が切れた場合ユーザーが動的ログインフローでログインできるようにします。

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

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

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

ユーザーが [続行] ボタンをクリックすると、ブラウザによって IdP のログインページのダイアログが開きます。

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

ログインページの URL は、IdP 構成ファイルの一部として login_url で指定します。

{
  "accounts_endpoint": "/auth/accounts",
  "client_metadata_endpoint": "/auth/metadata",
  "id_assertion_endpoint": "/auth/idtokens",
  "login_url": "/login"
  }
}

このダイアログは、ファーストパーティの Cookie が表示されている通常のブラウザ ウィンドウです。ダイアログ内での処理はすべて IdP により行われ、RP ページへのクロスオリジン通信リクエストに使用できるウィンドウ ハンドルはありません。ユーザーがログインすると、IdP は次のことを行う必要があります。

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

Login Status API の動作は、こちらのデモでお試しいただけます。

  1. [IdP にアクセスしてログイン] ボタンをタップします。
  2. 任意のアカウントでログインします。
  3. [Account Status] プルダウンから [Session Expired] を選択します。
  4. [個人情報を更新] ボタンを押します。
  5. [RP にアクセスして FedCM を試す] ボタンをタップします。

モジュールの動作を通じて、IdP へのログインをモニタリングできます。

エラー API

Chrome が ID アサーション エンドポイントにリクエストを送信したとき(ユーザーが FedCM UI で [Continue as] ボタンをクリックした場合や、自動再認証がトリガーされたときなど)、IdP は正当な理由でトークンを発行できないことがあります。たとえば、クライアントが承認されていないと、サーバーが一時的に使用不能になります。現在、Chrome ではこのようなエラーが発生した場合、通知なくリクエストが失敗し、Promise を拒否して RP に通知します。

Error API では、Chrome は IdP から提供されたエラー情報を含むネイティブ UI を表示して、ユーザーに通知します。

ユーザーのログイン試行が失敗した後のエラー メッセージを示す FedCM ダイアログ。この文字列はエラータイプに関連付けられます。
ユーザーのログイン試行が失敗した後、エラー メッセージが表示されている FedCM ダイアログ。文字列はエラータイプに関連付けられます。

IdP HTTP API

リクエスト時にトークンを発行できる場合、IdP は id_assertion_endpoint レスポンスでブラウザにトークンを返すことができます。このプロポーザルでは、トークンを発行できない場合、IdP は 2 つの新しいオプション フィールドを含む「エラー」レスポンスを返すことができます。

  1. code
  2. url
// id_assertion_endpoint response
{
  "error": {
     "code": "access_denied",
     "url": "https://idp.example/error?type=access_denied"
  }
}

コードについては、IdP は OAuth 2.0 で指定されたエラーリストinvalid_requestunauthorized_clientaccess_deniedserver_errortemporarily_unavailable)から既知のエラーのいずれかを選択するか、任意の文字列を使用できます。後者の場合、Chrome は汎用のエラー メッセージとともにエラー UI を表示し、コードを RP に渡します。

url は、エラーに関する情報を含む人が読める形式のウェブページを識別し、エラーに関する追加情報をユーザーに提供します。ブラウザはネイティブ UI でリッチエラー メッセージを表示できないため、このフィールドはユーザーにとって有用です。たとえば、次のステップやカスタマー サービスの連絡先情報へのリンクなどです。ユーザーがエラーの詳細と修正方法について知りたい場合は、ブラウザの UI から表示されたページにアクセスすると、詳細を確認できます。URL は、IdP configURL と同じサイトのものである必要があります。

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;
}

自動選択フラグ API

mediation: optional は、Credential Management API のデフォルトのユーザー メディエーション動作であり、可能な場合に自動再認証をトリガーします。ただし、自動再認証は、ブラウザしか認識できない理由で使用できない場合があります。使用できない場合、ユーザーは明示的なユーザー メディエーション(異なるプロパティを持つフロー)を使用してログインするよう求められる場合があります。

  • API の呼び出し元から見ると、ID トークンを受け取ったユーザーは、それが自動再認証フローの結果だったかどうかを把握できません。そのため、API のパフォーマンスを評価し、それに応じて UX を改善することが困難になっています。
  • IdP の観点からは、パフォーマンス評価で自動再認証が発生したかどうかを判別することはできません。また、明示的なユーザー メディエーションが関与しているかどうかは、より多くのセキュリティ関連機能のサポートに役立ちます。たとえば、ユーザーによっては、認証に明示的なユーザー メディエーションを必要とする上位のセキュリティ階層を選択する場合があります。IdP がこのようなメディエーションなしでトークン リクエストを受け取った場合は、リクエストの処理方法が異なる可能性があります。たとえば、RP が mediation: required で FedCM API を再度呼び出せるように、エラーコードを返します。

そのため、自動再認証フローを可視化することはデベロッパーにとって有益です。

Chrome は Auto-selected Flag API を介して、自動再認証が行われるか明示的なメディエーションが行われるたびに、[Continue as] ボタンをタップして IdP と RP の両方で明示的なユーザー権限を取得したかどうかを共有します。共有は、IdP/RP 通信のユーザー権限が付与された後にのみ行われます。

IdP の共有

ユーザーの権限後に IdP に情報を共有するため、Chrome では id_assertion_endpoint に送信される POST リクエストに is_auto_selected=true を含めます。

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=Ct0D&disclosure_text_shown=true&is_auto_selected=true

取引規制対象者の共有

ブラウザは、IdentityCredential を介して isAutoSelected の RP と情報を共有できます。

const cred = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: 'https://idp.example/manifest.json',
      clientId: '1234'
    }]
  }
});

if (cred.isAutoSelected !== undefined) {
  const isAutoSelected = cred.isAutoSelected;
}

フィードバックを共有

フィードバックがある場合や、テスト中に問題が発生した場合は、crbug.com でお知らせください。

写真撮影: Girl with red hat(出典: Unsplash