1. はじめに
最終更新日: 2023 年 2 月 23 日
Firebase リソースへの不正アクセスを防ぐにはどうすればよいですか?
Firebase App Check を使用すると、受信リクエストにリクエストが正規のアプリから発信されたものであることを証明する証明書を添付することを要求し、適切な証明書がないトラフィックをブロックすることで、未承認のクライアントがバックエンド リソースにアクセスするのを防ぐことができます。Firebase App Check は、プラットフォーム固有の証明書プロバイダを使用してクライアントの信頼性を検証します。ウェブアプリの場合、App Check は証明書プロバイダとして reCAPTCHA v3 と reCAPTCHA Enterprise をサポートしています。
App Check を使用すると、Cloud Firestore、Realtime Database、Cloud Functions、Identity Platform を使用する Firebase Authentication、およびお客様がホストするバックエンドへのリクエストを保護できます。
作成するアプリの概要
この Codelab では、まず App Check を追加してから適用することで、チャット アプリケーションを保護します。
学習内容
- バックエンドで不正アクセスをモニタリングする方法
- Firestore と Cloud Storage に適用を追加する方法
- ローカル開発用のデバッグ トークンを使用してアプリケーションを実行する方法
必要なもの
- 任意の IDE またはテキスト エディタ
- 通常は Node.js に付属しているパッケージ マネージャー npm
- Firebase CLI がインストールされ、アカウントで動作するように構成されている
- ターミナル/コンソール
- 任意のブラウザ(Chrome など)
- Codelab のサンプルコード(コードの取得方法については、Codelab の次の手順を参照してください)。
2. サンプルコードを取得する
コマンドラインから、Codelab の GitHub リポジトリのクローンを作成します。
git clone https://github.com/firebase/codelab-friendlychat-web
または、Git がインストールされていない場合は、リポジトリを ZIP ファイルとしてダウンロードすることもできます。
スターター アプリをインポートする
IDE を使用して、クローンされたリポジトリから 📁 appcheck-start
ディレクトリを開くか、インポートします。この 📁 appcheck-start
ディレクトリには、完全に機能するチャット ウェブアプリとなる Codelab の開始コードが含まれています。📁 appcheck
ディレクトリには、Codelab の完成したコードが含まれています。
3. Firebase プロジェクトを作成して設定する
Firebase プロジェクトを作成する
- Google アカウントを使用して Firebase コンソールにログインします。
- ボタンをクリックして新しいプロジェクトを作成し、プロジェクト名(例:
FriendlyChat
)を入力します。
- [続行] をクリックします。
- Firebase の利用規約が表示されたら、内容を読み、同意して [続行] をクリックします。
- (省略可)Firebase コンソールで AI アシスタンス(「Gemini in Firebase」)を有効にします。
- この Codelab では Google アナリティクスは必要ないため、Google アナリティクスのオプションをオフに切り替えます。
- [プロジェクトを作成] をクリックし、プロジェクトのプロビジョニングが完了するまで待ってから、[続行] をクリックします。
Firebase の料金プランをアップグレードする
Cloud Storage for Firebase を使用するには、Firebase プロジェクトが従量課金制(Blaze)のお支払いプランに登録されている必要があります。つまり、Cloud 請求先アカウントにリンクされている必要があります。
- Cloud 請求先アカウントには、クレジット カードなどの支払い方法が必要です。
- Firebase と Google Cloud を初めて使用する場合は、$300 のクレジットと無料トライアル用 Cloud 請求先アカウントを利用できるかどうかご確認ください。
- この Codelab をイベントの一環として行う場合は、利用可能な Cloud クレジットがあるかどうかを主催者に確認してください。
プロジェクトを Blaze プランにアップグレードする手順は次のとおりです。
- Firebase コンソールで、プランをアップグレードします。
- Blaze プランを選択します。画面の指示に沿って、Cloud 請求先アカウントをプロジェクトにリンクします。
このアップグレードの一環として Cloud 請求先アカウントを作成する必要があった場合は、Firebase コンソールのアップグレード フローに戻ってアップグレードを完了する必要がある場合があります。
プロジェクトに Firebase ウェブアプリを追加する
- ウェブアイコン
をクリックして、新しい Firebase ウェブアプリを作成します。
- Friendly Chat というニックネームでアプリを登録し、[このアプリの Firebase Hosting も設定します] の横のチェックボックスをオンにします。[アプリを登録] をクリックします。
- 次のステップでは、npm を使用して Firebase をインストールするコマンドと構成オブジェクトが表示されます。このオブジェクトは Codelab の後半でコピーするため、ここでは [次へ] をクリックします。
- Firebase CLI をインストールするオプションが表示されます。まだインストールしていない場合は、
npm install -g firebase-tools
コマンドを使用してインストールします。[次へ] をクリックします。 - Firebase にログインして Firebase Hosting にデプロイするオプションが表示されます。コマンド
firebase login
を使用して Firebase にログインし、[コンソールに進む] をクリックします。Firebase Hosting へのデプロイは、後のステップで行います。
Firebase プロダクトを設定する
これから構築するアプリケーションは、ウェブアプリに使用できる Firebase プロダクトを使用します。
- ユーザーがアプリに簡単にログインできるようにするための Firebase Authentication。
- 構造化されたデータをクラウドに保存し、データが変更されたときに即座に通知を受け取る Cloud Firestore。
- ファイルをクラウドに保存する Cloud Storage for Firebase。
- アセットをホストして提供する Firebase Hosting。
- プッシュ通知を送信し、ブラウザのポップアップ通知を表示する Firebase Cloud Messaging。
- Firebase Performance Monitoring を使用して、アプリのユーザー パフォーマンス データを収集します。
この中には、特別な設定が必要になるプロダクトや、Firebase コンソールを使用して有効化する必要があるプロダクトがあります。
Firebase Authentication 用に Google ログインを有効にする
ユーザーが Google アカウントでウェブアプリにログインできるように、Google ログインを使用します。
Google ログインを有効にする必要があります。
- Firebase コンソールの左側のパネルで、[構築] セクションを見つけます。
- [Authentication] をクリックし、必要に応じて [開始] をクリックしてから、[ログイン方法] タブをクリックします(または、ここをクリックして直接移動します)。
- Google ログイン プロバイダを有効にする
- アプリの公開名を「Friendly Chat」に設定し、プルダウン メニューからプロジェクトのサポート メールアドレスを選択します。
- [保存] をクリックします。
Cloud Firestore を設定する
このウェブアプリは Cloud Firestore を使用してチャット メッセージを保存し、新しいチャット メッセージを受信します。
Firebase プロジェクトで Cloud Firestore を設定する方法は次のとおりです。
- Firebase コンソールの左側のパネルで [ビルド] を展開し、[Firestore データベース] を選択します。
- [データベースを作成] をクリックします。
- [データベース ID] は
(default)
に設定したままにします。 - データベースの場所を選択し、[次へ] をクリックします。
実際のアプリでは、ユーザーに近い場所を選択します。 - [テストモードで開始] をクリックします。セキュリティ ルールに関する免責条項を確認します。
この Codelab の後半で、データを保護するためのセキュリティ ルールを追加します。データベースのセキュリティ ルールを追加せずに、アプリを配布または公開しないでください。 - [作成] をクリックします。
Cloud Storage for Firebase を設定する
このウェブアプリは Cloud Storage for Firebase を使用して画像ファイルを保存、アップロード、共有します。
Firebase プロジェクトで Cloud Storage for Firebase を設定する手順は次のとおりです。
- Firebase コンソールの左側のパネルで [ビルド] を展開し、[Storage] を選択します。
- [開始] をクリックします。
- デフォルトの Storage バケットのロケーションを選択します。
US-WEST1
、US-CENTRAL1
、US-EAST1
のバケットは、Google Cloud Storage の「無料枠」を利用できます。他のすべてのロケーションのバケットは、Google Cloud Storage の料金と使用量に従います。 - [テストモードで開始] をクリックします。セキュリティ ルールに関する免責条項を確認します。
この Codelab の後半で、データを保護するためのセキュリティ ルールを追加します。Storage バケットのセキュリティ ルールを追加せずに、アプリを配布または公開しないでください。 - [作成] をクリックします。
4. Firebase を構成する
appcheck-start
ディレクトリから、次のコマンドを呼び出します。
firebase use --add
プロンプトが表示されたら、プロジェクト ID を選択して、Firebase プロジェクトにエイリアスを指定します。このプロジェクトでは、エイリアスとして default を指定します。次に、Firebase を使用するようにローカル プロジェクトを構成する必要があります。
- Firebase コンソールのプロジェクト設定に移動します。
- [アプリ] カードで、構成オブジェクトが必要なアプリのニックネームを選択します。
- Firebase SDK スニペット ペインで [Config] を選択します。
- 構成オブジェクト スニペットをコピーして、
appcheck-start/hosting/src/firebase-config.js
に追加します。この Codelab の残りの部分では、変数が config という名前であると想定しています。
firebase-config.js
const config = {
apiKey: "API_KEY",
authDomain: "PROJECT_ID.firebaseapp.com",
databaseURL: "https://PROJECT_ID.firebaseio.com",
projectId: "PROJECT_ID",
storageBucket: "PROJECT_ID.firebasestorage.app",
messagingSenderId: "SENDER_ID",
appId: "APP_ID",
measurementId: "G-MEASUREMENT_ID",
};
同じ appcheck-start
ディレクトリから、次のコマンドを呼び出します。
firebase experiments:enable webframeworks
これにより、このプロジェクトの構築に使用されたウェブ フレームワークのサポートが有効になります。
これで、プロジェクトを実行して、デフォルト プロジェクトが機能することをテストする準備が整いました。
5. App Check を使用せずにアプリを試す
アプリの設定と SDK のセットアップが完了したら、アプリを本来の設計どおりに使用してみてください。まず、すべての依存関係をインストールします。ターミナルから appcheck-start/hosting
ディレクトリに移動します。そのディレクトリ内で npm install
を実行します。これにより、プロジェクトが動作するために必要なすべての依存関係が取得されます。現在の状態でアプリを起動するには、firebase serve
を実行します。アプリで Google アカウントでのログインが求められるので、ログインしてから、チャットにいくつかのチャット メッセージと写真を投稿してみます。
ローカルでテストしたので、本番環境で確認してみましょう。firebase deploy
を実行して、ウェブ アプリケーションをウェブにデプロイします。この部分は、reCAPTCHA Enterprise 認証プロバイダ用にドメインを構成する必要があるため、App Check が実際にどのように機能するかをデモするうえで重要なステップです。
アプリが提供するデフォルトの機能をご利用いただけていることと思います。チャット メッセージの投稿など、このようなアプリからのみ行うべき操作。現在の状態の欠点は、前の手順でアプリの構成を取得したユーザーがバックエンド リソースにアクセスできることです。Firestore と Cloud Storage システムで設定されているセキュリティ ルールは引き続き遵守する必要がありますが、それ以外の場合は、そこに保存されているデータのクエリ、保存、アクセスを行うことができます。
次の手順では、次の操作を行います。
- App Check に登録する
- 適用を検証する
- ルールの適用を開始する
6. App Check と適用を有効にする
まず、プロジェクトの reCAPTCHA Enterprise キーを取得して App Check に追加します。まず、Google Cloud コンソールの [reCAPTCHA Enterprise] セクションにアクセスします。プロジェクトを選択すると、reCAPTCHA Enterprise API を有効にするよう求めるメッセージが表示されます。API を有効にして、完了するまで数分待ちます。[エンタープライズ キー] の横にある [キーを作成] をクリックします。このセクションで、表示名を指定し、[ウェブサイト] タイプのキーを選択します。アプリをホストするドメインを指定する必要があります。Firebase Hosting でホストする予定なので、通常は ${YOUR_PROJECT_ID}.web.app
であるデフォルトのホスティング名を使用します。ホスティング ドメインは、Firebase コンソールの [Hosting] セクションで確認できます。この情報を入力したら、[完了]、[キーを作成] の順にクリックします。
完了すると、[キーの詳細] ページの上部に ID が表示されます。
この ID をクリップボードにコピーします。これは App Check に使用するキーです。次に、Firebase コンソールの [App Check] セクションに移動し、[始める] をクリックします。[登録] をクリックし、[reCAPTCHA Enterprise] をクリックして、コピーした ID を [reCAPTCHA Enterprise サイトキー] のテキスト ボックスに貼り付けます。その他の設定はデフォルトのままにします。アプリのチェックページは次のようになります。
未確認で実施されていないリクエスト
Firebase コンソールに登録されたキーが作成されたので、firebase serve
を実行してブラウザでサイトの実行に戻ります。これでウェブアプリがローカルで実行され、Firebase バックエンドに対してリクエストを再び送信できるようになりました。リクエストは Firebase バックエンドに対して行われるため、これらのリクエストは App Check によってモニタリングされますが、適用はされません。リクエストのステータスを確認するには、Firebase コンソールの App Check ページの [API] タブにある Cloud Firestore セクションにアクセスします。クライアントで App Check を使用するようにまだ構成していないため、次のようなメッセージが表示されます。
バックエンドに 100% の未確認リクエストが届いています。この画面は、クライアント リクエストのほとんどが App Check を統合していないクライアントから送信されていることを示しているため、有用です。
このダッシュボードには、いくつかの情報が表示されます。まず、すべてのクライアント アプリが最新バージョンのクライアントを実行しているかどうかを確認できます。その場合は、アプリケーションの正規のクライアントのアクセスをオフにする心配をせずに、App Check を安全に適用できます。また、アプリ内からではなくバックエンドにアクセスしようとした試行回数もわかります。これは、ユーザーが知らないうちにバックエンドに直接クエリを実行している可能性があることを示しています。リクエストが確認されていないことがわかったので、リクエストの確認に進む前に、バックエンドへのリクエストが確認されていないユーザーに何が起こるかを確認します。
未確認で実施されたリクエスト
前の画面で [適用] ボタンを押し、メッセージが表示されたらもう一度 [適用] を押します。
これにより、App Check の適用が開始され、選択した証明書プロバイダ(この場合は reCAPTCHA Enterprise)で検証されていないバックエンド サービスへのリクエストがブロックされるようになります。http://localhost:5000
で実行されている実行中のウェブアプリに戻ります。ページを更新してデータベースからデータを取得しようとしても、何も起こりません。Chrome コンソールを開いてエラーを確認すると、次のような内容が表示されます。
Uncaught Error in snapshot listener: FirebaseError: [code=permission-denied]: Missing or insufficient permissions.
これは、Firebase リソースに対するリクエストで有効な証明書トークンが渡されなかったリクエストを App Check がブロックしたものです。当面の間は、App Check の適用を無効にできます。次のセクションでは、Friendly Chat の例に reCAPTCHA Enterprise App Check を追加する方法について説明します。
7. サイトに reCAPTCHA Enterprise キーを追加する
エンタープライズ キーをアプリケーションに追加します。まず、hosting/src/firebase-config.js
を開き、次のコード スニペットに reCAPTCHA Enterprise キーを追加します。
const reCAPTCHAEnterpriseKey = {
// Replace with your recaptcha enterprise site key
key: "Replace with your recaptcha enterprise site key"
};
完了したら、hosting/src/index.js
を開きます。51 行目に firebase-config.js からのインポートを追加して、reCAPTCHA キーを取得し、App Check ライブラリをインポートして、reCAPTCHA Enterprise プロバイダを使用できるようにします。
// add from here
import {
initializeAppCheck,
ReCaptchaEnterpriseProvider,
} from 'firebase/app-check';
// to here
// replace this line
import { getFirebaseConfig } from './firebase-config.js';
// with this line
import { getFirebaseConfig, getReCaptchaKey } from './firebase-config.js';
次の行で、App Check を設定する関数を作成します。この関数は、まず開発環境にいるかどうかを確認し、開発環境にいる場合は、ローカル開発で使用できるデバッグトークンを出力します。
import { getFirebaseConfig, getReCaptchaKey } from './firebase-config.js';
// add from here
function setupAppCheck(app) {
if(import.meta.env.MODE === 'development') {
self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
}
}
// to here
次に、選択したプロバイダ(この場合は reCAPTCHA Enterprise)で動作するように App Check を初期化します。また、App Check トークンが古くなった場合にユーザーがサービスを操作する際の遅延を防ぐため、App Check トークンをバックグラウンドで自動的に更新することもおすすめします。
function setupAppCheck(app) {
if(import.meta.env.MODE === 'development') {
self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
}
// add from here
// Create a ReCaptchaEnterpriseProvider instance using your reCAPTCHA Enterprise
// site key and pass it to initializeAppCheck().
initializeAppCheck(app, {
provider: new ReCaptchaEnterpriseProvider(getReCaptchaKey()),
isTokenAutoRefreshEnabled: true // Set to true to allow auto-refresh.
});
// to here
}
最後に、アプリが初期化されたことを確認したら、作成した setupAppCheck 関数を呼び出す必要があります。hosting/src/index.js
ファイルの下部に、先ほど追加したメソッドの呼び出しを追加します。
const firebaseApp = initializeApp(getFirebaseConfig());
// add from here
setupAppCheck(firebaseApp);
// to here
getPerformance();
initFirebaseAuth();
loadMessages();
まずはローカルでテストする
まず、アプリケーションをローカルでテストします。アプリケーションをローカルで提供していない場合は、firebase serve
を実行します。アプリケーションがローカルで読み込まれないことがわかります。これは、Firebase ドメインのみを reCAPTCHA 認証プロバイダに登録し、localhost ドメインを登録していないためです。localhost を承認済みドメインとして登録しないでください。これにより、ユーザーは自分のマシンでローカルに実行されているアプリケーションから制限付きバックエンドにアクセスできるようになります。代わりに、self.FIREBASE_APPCHECK_DEBUG_TOKEN = true
を設定した場合は、JavaScript コンソールで次のような行を確認します。
App Check debug token: 55183c20-de61-4438-85e6-8065789265be. You will need to add it to your app's App Check settings in the Firebase console for it to work.
提供されたデバッグトークン(この例では 55183c20-de61-4438-85e6-8065789265be
)を取得し、アプリのオーバーフロー メニューにある App Check 構成に挿入します。
覚えやすい一意の名前をトークンに付けて、[保存] をクリックします。このオプションを使用すると、アプリでクライアント生成トークンを使用できます。これは、デバッグトークンを生成してアプリケーションに埋め込むよりも安全な方法です。アプリ内にトークンを埋め込むと、エンドユーザーに誤って配布される可能性があり、エンドユーザーがチェックをバイパスしてトークンを悪用する可能性があります。デバッグトークンを配布する場合(CI 環境など)は、こちらのドキュメントで配布方法をご確認ください。
Firebase コンソールにデバッグトークンを登録したら、App Check の適用を再度有効にして、ターミナルから firebase serve
を呼び出してアプリのコンテンツがローカルで読み込まれることをテストできます。以前に入力したデータがウェブ アプリケーションのローカル バージョンに提供されていることがわかります。デバッグ トークンを含むメッセージがコンソールに出力されます。
本番環境で試す
App Check がローカルで動作することを確認したら、ウェブ アプリケーションを本番環境にデプロイします。ターミナルから firebase deploy
を再度呼び出し、ページを再読み込みします。これにより、ウェブ アプリケーションがパッケージ化され、Firebase Hosting で実行できるようになります。アプリケーションが Firebase Hosting でホストされたら、${YOUR_PROJECT_ID}.web.app
でアプリケーションにアクセスしてみてください。JavaScript コンソールを開くと、デバッグ トークンがそこに表示されなくなり、プロジェクトでチャットが読み込まれるようになります。また、アプリケーションをしばらく操作した後、Firebase コンソールの [App Check] セクションにアクセスして、アプリケーションへのリクエストがすべて検証済みになっていることを確認できます。
8. 完了
これで、Firebase App Check をウェブアプリに正常に追加できました。
Firebase コンソールを設定して、本番環境の reCAPTCHA Enterprise トークンを処理し、ローカル開発用のデバッグトークンを設定することもできます。これにより、アプリは承認済みのクライアントから Firebase リソースに引き続きアクセスできるようになり、アプリ内での不正行為を防ぐことができます。
次のステップ
Firebase App Check を追加するには、次のドキュメントをご覧ください。