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 ではデフォルトでフィルタされます。アタッチできるのは、デジタル アセットのリンクで確認された、同じオリジンのクライアントとサーバーのみです。