ブラウザーでサードパーティの Cookie ブロックを処理する方法
多くのブラウザーでは、 サードパーティの cookie、ブラウザーのアドレスバーに表示されているドメイン以外のドメインに対する要求の cookie がブロックされています。 これらのクッキーは、クロスドメイン Cookie とも呼ばれます。 このブロックにより、暗黙的なフローが中断され、ユーザーを正常にサインインさせるための新しい認証パターンが必要になります。 Microsoft ID プラットフォームでは、サードパーティの Cookie がブロックされている場合にユーザーのサインインを維持するために、Proof Key for Code Exchange (PKCE) と更新トークンで承認フローを使用します。 この承認コード フローと Proof Key for Code Exchange アプローチは、暗黙的なフローよりも推奨されます。
インテリジェント追跡保護 (ITP) とプライバシー サンドボックスとは
Apple Safari では、Intelligent Tracking Protection (ITP) と呼ばれるプライバシー保護機能が既定でオンになっています。 Chrome には、プライバシー サンドボックスというブラウザー プライバシー イニシアティブがあります。 これらのイニシアティブには、ブラウザーによって異なる多数のブラウザー プライバシーに関する取り組みがあり、タイムラインも異なります。 どちらの取り組みでも、ドメインをまたがる要求の "サードパーティ" Cookie をブロックしており、Safari と Brave は既定でサードパーティ Cookie をブロックしています。 最近、Chrome はサードパーティ Cookie の既定でのブロックを開始することを発表しました。 プライバシー サンドボックスには、パーティション分割ストレージへの変更とサードパーティ Cookie のブロックが含まれています。
一般的な形式のユーザー追跡は、バックグラウンドで iframe をサードパーティ サイトに読み込み、Cookie を使用してインターネット経由でユーザーを関連付けることによって行われます。 残念ながら、このパターンは、シングルページ アプリ (SPA) で暗黙的なフローを実装するための標準的な方法でもあります。 ユーザーのプライバシーを保護するためにサードパーティの Cookie をブロックするブラウザーは、SPA の機能をブロックすることもできます。 サードパーティの Cookie のブロックと、それに関連するセキュリティ リスクのため、SPA での暗黙的なフローの使用は推奨されなくなりました。
この記事で概説するソリューションは、これらすべてのブラウザー、またはサードパーティの Cookie がブロックされるあらゆる場所で機能します。
ソリューションの概要
SPA でユーザーの認証を続行するには、アプリ開発者が認可コード フローを使用する必要があります。 認可コード フローでは、ID プロバイダーによってコードが発行され、SPA でアクセス トークンと更新トークンのコードが引き換えられます。 アプリで新しいトークンが必要な場合は、更新トークンのフローを使って新しいトークンを取得できます。 JavaScript v2.0 以上用の Microsoft Authentication Library (MSAL) では、SPA の認可コード フローを実装し、マイナー更新を行って、MSAL.js 1.x の代わりとして、そのまま使用することができます。 SPA を暗黙的なコード フローから認証コード フローに移行するには、移行ガイドを参照してください。
Microsoft ID プラットフォームの場合、SPA とネイティブ クライアントでは以下の同様のプロトコル ガイダンスに従います。
- PKCE コード チャレンジを使用する
- Microsoft ID プラットフォーム上の SPA では、PKCE が "必須" となります。 ネイティブおよび Confidential クライアントでは、PKCE が "推奨" されます。
- クライアント シークレットを使用しない
SPA にはさらに 2 つの制約があります。
- ログイン エンドポイントで CORS を有効にするには、リダイレクト URI が
spa
という種類としてマークされている必要があります。 spa
リダイレクト URI に認可コード フローを通じて発行される更新トークンには、90 日の有効期間ではなく、24 時間の有効期間があります。
パフォーマンスと UX への影響
暗黙的なフローを使用する一部のアプリケーションでは、prompt=none
を使ってログイン iframe を開くことで、リダイレクトすることなくサインインが試行されます。 ほとんどのブラウザーでは、この要求で、現在サインインしているユーザーのトークンを使用して応答します (同意が得られていることが前提)。 このパターンは、アプリケーションでユーザーをサインインさせるためのフル ページ リダイレクトが不要であり、パフォーマンスとユーザー エクスペリエンスが向上することを意味していました。この場合、ユーザーは Web ページにアクセスし、既にサインインしています。 サードパーティの Cookie がブロックされている場合、iframe の prompt=none
はオプションではなくなるため、アプリケーションでは、サインイン パターンを調整して認可コードを発行する必要があります。
サードパーティの Cookie がない場合、サインインを実現するには、次の 2 つの方法があります。
- フル ページ リダイレクト
- SPA の最初の読み込み時に、セッションがまだ存在しない場合 (またはセッションの有効期限が切れている場合) に、ユーザーをサインイン ページにリダイレクトします。 ユーザーのブラウザーではログイン ページにアクセスし、ユーザー セッションを含む Cookie を提示してから、フラグメントのコードとトークンを使用してアプリケーションに再びリダイレクトします。
- このリダイレクトによって、SPA が 2 回読み込まれることになります。 SPA のキャッシュのベスト プラクティスに従って、アプリが 2 度にわたって完全にダウンロードされないようにします。
- アプリで JavaScript ペイロードを完全にアンパックして実行する前に、ログイン セッションを確認し、ログイン ページにリダイレクトするアプリではプリロード シーケンスを使用することを検討してください。
- ポップアップ
- フル ページ リダイレクトのユーザー エクスペリエンス (UX) がアプリケーションで機能しない場合は、ポップアップを使用して認証を扱うことを検討してください。
- 認証後にポップアップでアプリケーションへのリダイレクトが完了すると、リダイレクト ハンドラーのコードによって、アプリケーションで使用するためにローカル ストレージに認証コードとトークンが格納されます。 MSAL.js では、ほとんどのライブラリの場合と同様に、認証用のポップアップがサポートされています。
- ブラウザーではポップアップのサポートが減少しているため、最も信頼性の高いオプションではない場合があります。 ブラウザーの要件を満たすには、ポップアップを作成する前にユーザーと SPA とのやり取りが必要になる場合があります。
Apple では、元のウィンドウからサードパーティの Cookie にアクセスできるようにするための一時的な互換性修正プログラムとして、ポップアップ手法について説明しています。 Apple は今後、アクセス許可のこの移転をなくす可能性がありますが、このガイダンスには影響しません。
ここでは、ログイン ページへのファースト パーティのナビゲーションとしてポップアップが使用されているため、セッションが検出され、認可コードを提供できます。 そのため、今後も引き続きご利用いただけるはずです。
開発者は、サード パーティの Cookie がブロックされたときに interacion_required エラーの割合が高くなることを期待して、prompt=none
を引き続き使用できます。 サイレント トークンの取得中にエラーが発生した場合は、常に 対話型メソッド フォールバックを使用することをおすすめします。
Iframe の使用
Web アプリ の一般的なパターンでは、iframe を使用して 1 つのアプリを別のアプリケーションに埋め込みます。最上位レベルのフレーム ハンドルはユーザーを認証し、iframe でホストされるアプリケーションは、ユーザーがサインインしていることを信頼し、暗黙的なフローを使用してトークンを警告なしにフェッチします。 ただし、ブラウザーでサードパーティの Cookie が有効になっているかブロックされているかに関係なく、この想定にはいくつかの注意事項があります。
サードパーティの Cookie がブロックされている場合、サイレント トークンの取得は機能しなくなりました。つまり、iframe に埋め込まれたアプリケーションでは、埋め込みフレーム内のログイン ページに移動できないため、ポップアップを使用してユーザーのセッションにアクセスするように切り替える必要があります。
親アプリから iframed アプリにユーザー (アカウント) ヒントを渡すことにより、同じオリジン と クロスオリジンのJavaScript スクリプト API アクセスで、iframeのアプリ と親アプリの間でシングルサインオンを実現できます。 詳細については、「GitHub の MSAL.js リポジトリのiframアプリでの MSAL.js の使用」を参照してください。
ブラウザーでの更新トークンのセキュリティへの影響
クロスサイト スクリプティング (XSS) 攻撃または JS パッケージの侵害により、更新トークンが盗まれ、有効期限が切れるか失効するまでリモートで使用される可能性があります。 アプリケーション開発者には、クロスサイト スクリプティングに対するアプリケーションのリスクを軽減する責任があります。 盗まれた更新トークンのリスクを最小限に抑えるために、SPA には 24 時間のみ有効なトークンが発行されます。 24 時間後、アプリでは、ログイン ページにアクセスするために最上位フレームを介して新しい認証コードを取得する必要があります。
この有効期間が制限された更新トークンのパターンは、セキュリティと低下した UX のバランスを取るために選ばれました。 更新トークンやサードパーティの Cookie がないと、新しいトークンまたは追加のトークンが必要になったときに、認可コード フロー (OAuth セキュリティのベスト プラクティス ドラフトで推奨) が煩雑になります。 トークンが期限切れになるたび (Microsoft ID プラットフォームのトークンの場合、通常は 1 時間ごと) に、すべてのシングル トークンでフル ページ リダイレクトまたはポップアップが必要になります。
ユーザーの種類固有の軽減策
すべてのユーザーとアプリケーションがサードパーティの Cookie による影響を一様に受けるわけではありません。 アーキテクチャまたはデバイスの管理により、サード パーティの Cookie なしでトークンを更新するためのサイレント呼び出しを実行できるシナリオがいくつかあります。
マネージド エンタープライズ デバイスのシナリオでは、特定のブラウザーとプラットフォームの組み合わせで、デバイスの条件付きアクセスがサポートされます。 認証状態はブラウザーではなくデバイスから取得できるため、デバイス ID を適用することで、サードパーティの Cookie の必要性を最小限に抑えることができます。
Azure AD B2C アプリケーションのシナリオの場合、お客様はアプリケーションのドメインに合わせてカスタム ログイン ドメインを設定できます。 このシナリオでは、Cookie が同じドメイン (login.contoso.com
から app.contoso.com
など) に残るため、ブラウザーはサードパーティの Cookie をブロックしません。
サード パーティの Cookie のないフロント チャネル ログアウトに関する制限事項
SPA からユーザーをサインアウトする場合、MSAL.js では、ポップアップ メソッドまたはリダイレクト ログアウト メソッドを使用することをおすすめします。 これにより、サーバーとブラウザー ストレージの認証セッションがクリアされますが、サードパーティの Cookie にアクセスしないと、一部のフェデレーション アプリケーションでサインアウトが同時に表示されないリスクが生じます。 これは、OpenID Front-Channel Logout 1.0 仕様の既知の制限です。 これがユーザーにとって意味することは、同じユーザーに対して他のアプリケーションのアクセス トークンが既にある場合、有効期限が切れるまでは引き続き有効であるということです。 ユーザーがタブ A のアプリケーション A からログアウトしたとしても、アクセス トークンの残りの有効期間中は、タブ B のアプリケーション B には引き続きログイン済みと表示されます。 アプリケーション B のトークンの有効期限が切れ、新しいトークンを取得するためにサーバーへの呼び出しが行われると、アプリケーション B はサーバーからセッションの有効期限が切れたという応答を受け取り、ユーザーに認証を求めます。
Microsoft のサインアウト ページとインターネット プライバシーのベスト プラクティスでは、ユーザーがアプリケーションからログアウトした後にすべてのブラウザー ウィンドウを閉じることをおすすめしています。
次のステップ
承認コードフローと MSAL.js の詳細については、以下を参照してください。