HTTP リクエストには、User-Agent や Content-Type などのヘッダーが含まれます。ブラウザによって付加されるヘッダー以外に、Android アプリは EXTRA_HEADERS
インテント エクストラを使用して、Cookie や Referrer などの追加ヘッダーを追加できます。セキュリティ上の理由から、Chrome は、インテントの起動方法と場所に応じて、一部の追加ヘッダーをフィルタします。
クロスオリジン リクエストでは、クライアントとサーバーが同じ所有者ではないため、追加のセキュリティ レイヤが必要です。このガイドでは、Chrome のカスタムタブを介したこのようなリクエストの開始について説明します。つまり、ブラウザのタブで URL を開くアプリから起動されるインテントを指します。Chrome 83 までは、カスタムタブの起動時に任意のヘッダーを追加できました。バージョン 83 以降、Chrome では、承認リストに登録されていないヘッダーがセキュリティ リスクとなるため、承認リストに登録されているクロスオリジン ヘッダーを除くすべてのヘッダーのフィルタリングを開始しました。Chrome 86 以降では、サーバーとクライアントがデジタル アセットリンクを使用して関連付けられている場合、承認リストに登録されていないヘッダーをクロスオリジン リクエストに添付できます。この動作を次の表にまとめます。
Chrome のバージョン | 許可される CORS ヘッダー |
---|---|
Chrome 83 より前 | 承認リスト、承認リストにない |
Chrome 83 ~ Chrome 85 | 承認リストに登録済み |
Chrome 86 以降 | 承認リストに登録、デジタル アセット リンクが設定されている場合は承認リストに登録されていません |
表 1.: 承認リストにない CORS ヘッダーのフィルタリング。
この記事では、サーバーとクライアントの間に確認済みの接続を設定し、それを使用して、承認リストにある http ヘッダーと承認されていない http ヘッダーを送信する方法について説明します。コードについては、カスタムタブ インテントに追加のヘッダーを追加するに進んでください。
背景
承認リストに登録された CORS リクエスト ヘッダーと非承認リストに登録されていない CORS リクエスト ヘッダー
クロスオリジン リソース シェアリング(CORS)を使用すると、ある生成元のウェブ アプリケーションが別の生成元のリソースをリクエストできます。CORS 承認リストに登録されているヘッダーのリストは、HTML 標準で管理されています。承認リストに登録されているヘッダーの例を次の表に示します。
ヘッダー | 説明 |
---|---|
accept-language | クライアントが理解できる自然言語をアドバタイズします。 |
content-language | 現在のオーディエンス向けの言語を説明します |
content-type | リソースのメディアタイプを示します。 |
表 2.: 承認リストに登録されている CORS ヘッダーの例。
承認リストに登録されているヘッダーは、機密性の高いユーザー情報を含まず、サーバーが有害な操作を実行する可能性も低いため、安全と見なされます。
次の表に、承認対象から除外されるヘッダーの例を示します。
ヘッダー | 説明 |
---|---|
bearer-token | サーバーでクライアントを認証する |
オリジン | リクエストの送信元を示します |
Cookie | サーバーによって設定された Cookie が含まれている |
表 3.: 承認リストに登録されていない CORS ヘッダーの例。
承認リストに登録されていないヘッダーを CORS リクエストに添付することは、HTML 標準で推奨されていません。サーバーは、クロスオリジン リクエストに承認リストに登録されているヘッダーのみが含まれていることを前提としています。クロスオリジン ドメインから承認リストにないヘッダーを送信すると、悪意のあるサードパーティ製アプリが、Chrome(または他のブラウザ)が保存してリクエストに添付するユーザー Cookie を不正使用するヘッダーを作成できるようになります。Cookie を使用すると、不正なサーバー トランザクションを認証できます。
カスタムタブ リクエストに CORS 許可リストに登録されたヘッダーを添付する
カスタムタブは、カスタマイズされたブラウザタブでウェブページを起動する特別な方法です。カスタムタブ インテントを作成するには、CustomTabsIntent.Builder()
を使用します。Browser.EXTRA_HEADERS
フラグを指定して Bundle
を使用して、これらのインテントにヘッダーを添付することもできます。
CustomTabsIntent intent = new CustomTabsIntent.Builder(session).build();
Bundle headers = new Bundle();
headers.putString("bearer-token", "Some token");
headers.putString("redirect-url", "Some redirect url");
intent.intent.putExtra(Browser.EXTRA_HEADERS, headers);
intent.launchUrl(Activity.this, Uri.parse("http://www.google.com"));
承認リストに登録されているヘッダーは、カスタムタブの CORS リクエストにいつでも追加できます。ただし、Chrome ではデフォルトで、承認リストに登録されていないヘッダーがフィルタされます。他のブラウザでは動作が異なる場合がありますが、デベロッパーは、承認リストにないヘッダーがブロックされることを想定する必要があります。
未承認のヘッダーをカスタムタブに含めるには、まずデジタル アクセスリンクを使用してクロスオリジン接続を確認します。次のセクションでは、これらを設定し、必要なヘッダーを使用してカスタムタブ インテントを起動する方法について説明します。
カスタムタブ インテントに追加のヘッダーを追加する
デジタル アセット リンクを設定する
承認リストに登録されていないヘッダーをカスタムタブ インテント経由で渡すには、作成者が両方のアプリを所有していることを確認する Android アプリとウェブアプリの間にデジタル アセットリンクを設定する必要があります。
公式ガイドに沿ってデジタル アセットのリンクを設定します。リンク関係には「delegate_permission/common.use_as_origin」を使用します。これは、リンクが検証されると、両方のアプリが同じオリジンに属することを示します。
追加ヘッダーを使用してカスタムタブ インテントを作成する
カスタムタブ インテントを作成するには、複数の方法があります。androidX で利用可能なビルダーを使用するには、ライブラリをビルド依存関係に追加します。
MULTI_LINE_CODE_PLACEHOLDER_1
インテントを作成し、追加のヘッダーを追加します。
MULTI_LINE_CODE_PLACEHOLDER_2
カスタムタブ接続を設定してアセットリンクを検証する
カスタム タブ接続は、アプリと Chrome タブの間に CustomTabsSession
を設定するために使用されます。アプリとウェブアプリが同じオリジンに属していることを確認するには、セッションが必要です。デジタル アセット リンクが正しく設定されている場合にのみ、検証に合格します。
CustomTabsClient.warmup()
を呼び出すことをおすすめします。これにより、ブラウザ アプリケーションをバックグラウンドで事前初期化し、URL の開くプロセスを高速化できます。
MULTI_LINE_CODE_PLACEHOLDER_3
検証後にインテントを起動するコールバックを設定する
CustomTabsCallback
がセッションに渡されました。onRelationshipValidationResult()
は、オリジンの検証が成功すると、以前に作成した CustomTabsIntent
を起動するように設定されています。
MULTI_LINE_CODE_PLACEHOLDER_4
カスタムタブ サービス接続をバインドする
サービスをバインドすると、サービスが起動され、接続の onCustomTabsServiceConnected()
が最終的に呼び出されます。サービスを適切に解除してください。バインドとバインド解除は、一般に onStart()
と onStop()
のアクティビティのライフサイクル メソッドで行われます。
// Bind the custom tabs service connection.
// Call this in onStart()
CustomTabsClient.bindCustomTabsService(this,
CustomTabsClient.getPackageName(MainActivity.this, null), connection);
// …
// Unbind the custom tabs service.
// Call this in onStop().
unbindService(connection);
デモ アプリケーション コード
カスタムタブ サービスの詳細については、こちらをご覧ください。実際に動作するサンプルアプリについては、android-browser-helper GitHub リポジトリをご覧ください。
概要
このガイドでは、カスタムタブの CORS リクエストに任意のヘッダーを追加する方法について説明しました。承認リストに登録されているヘッダーは、すべてのカスタムタブの CORS リクエストに追加できます。承認リストにないヘッダーは通常、CORS リクエストで安全でないものと見なされ、Chrome ではデフォルトでフィルタされます。アタッチできるのは、デジタル アセットのリンクによって確認された、同じオリジンのクライアントとサーバーのみです。