Chrome 120 では、FedCM 向けの Login Status 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-in
、logged-out
、unknown
です。デフォルトの状態は 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 呼び出しを失敗させます。
ユーザー セッションの有効期限が切れた場合はどうなりますか?ユーザーが動的ログインフローを使用してログインできるようにします。
ID プロバイダがユーザーのログイン ステータスをブラウザに継続的に通知している場合でも、セッションが期限切れになったときなど、ステータスが同期されていない可能性があります。ログイン ステータスが logged-in
の場合、ブラウザは認証情報付きのリクエストをアカウント リスト エンドポイントに送信しようとしますが、セッションが使用できなくなったため、サーバーからアカウントが返されません。このようなシナリオでは、ブラウザはダイアログ ウィンドウからユーザーが IdP にログインできるように動的に設定できます。
次の図に示すように、FedCM ダイアログにログインを求めるメッセージが表示されます。

ユーザーが [続行] ボタンをクリックすると、ブラウザで 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()
を呼び出してダイアログを閉じます。

Login Status API の動作は、デモで試すことができます。
- [IdP に移動してログイン] ボタンをタップします。
- 任意のアカウントでログインします。
- [アカウントのステータス] プルダウンから [セッションが期限切れ] を選択します。
- [個人情報を更新] ボタンを押します。
- [RP にアクセスして FedCM を試す] ボタンをタップします。
モジュールの動作から、IdP へのログインを観察できるはずです。
Error API
Chrome が ID アサーション エンドポイントにリクエストを送信すると(ユーザーが FedCM UI の [Continue as] ボタンをクリックしたときや、自動再認証がトリガーされたときなど)、IdP が正当な理由でトークンを発行できない場合があります。たとえば、クライアントが認証されていない場合や、サーバーが一時的に使用できない場合などです。現在、Chrome はこのようなエラーが発生した場合、リクエストをサイレントで失敗させ、Promise を拒否することで RP に通知するだけです。
Error API を使用すると、Chrome は IdP から提供されたエラー情報を含むネイティブ UI を表示してユーザーに通知します。

IdP HTTP API
id_assertion_endpoint
レスポンスで、IdP はリクエストに応じてトークンを発行できる場合は、ブラウザにトークンを返すことができます。このプロポーザルでは、トークンを発行できない場合、IdP は「error」レスポンスを返すことができます。このレスポンスには、2 つの新しいオプション フィールドがあります。
code
url
// id_assertion_endpoint response
{
"error": {
"code": "access_denied",
"url": "https://idp.example/error?type=access_denied"
}
}
コードの場合、IdP は OAuth 2.0 で指定されたエラーリスト [invalid_request
、unauthorized_client
、access_denied
、server_error
、temporarily_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;
}
Auto-Selected Flag API
mediation: optional
は、認証情報管理 API のデフォルトのユーザー メディエーション動作であり、可能であれば自動再認証をトリガーします。ただし、ブラウザにのみわかる理由により、自動再認証が利用できない場合があります。利用できない場合は、ユーザーが明示的に操作してログインするよう求められます。これは、プロパティが異なるフローです。
- API 呼び出し元の視点から見ると、ID トークンを受け取ったときに、それが自動再認証フローの成果であるかどうかを把握することはできません。そのため、API のパフォーマンスを評価して UX を改善することが困難になります。
- IdP の視点から見ると、パフォーマンス評価のために自動再認証が行われたかどうかを判断することもできません。また、明示的なユーザー メディエーションが関与しているかどうかは、セキュリティ関連の機能をより多くサポートするうえで役立ちます。たとえば、認証で明示的なユーザー仲介を必要とする、より高いセキュリティ ティアを希望するユーザーもいます。このようなメディエーションなしで IdP がトークン リクエストを受信した場合、リクエストを異なる方法で処理する可能性があります。たとえば、RP が
mediation: required
を使用して FedCM API を再度呼び出せるように、エラーコードを返します。
そのため、自動再認証フローの可視化はデベロッパーにとって有益です。
Auto-selected Flag API を使用すると、Chrome は、自動再認証が発生したときや明示的なメディエーションが発生したときに、[このユーザーとして続行] ボタンをタップして明示的なユーザー権限が取得されたかどうかを 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
RP の共有
ブラウザは、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 で共有できます。
写真: 赤い帽子をかぶった女の子(Unsplash)