FirebaseGoogle 

我がFirebaseアプリケーションを不正アクセスから守るFirebase App Check

はいさい!ちゅらデータぬオースティンやいびーん!

今日は、我がFirebaseアプリケーションを不正アクセスから守る、Firebase App Checkをご紹介したいと思います。

App Checkとは

Firebaseの正式ドキュメント(https://firebase.google.com/docs/app-check)から引用しますと以下の通りになります。

App Check は、承認されていないクライアントがバックエンド リソースにアクセスするのを防ぐことで、API リソースを悪用から保護するのに役立ちます。 Firebase サービス、Google Cloud サービス、および独自の API の両方と連携して、リソースを安全に保ちます。

つまり、ボットによるサイトスクレイピング、ハッキング攻撃等を検知して防ぐのに役立つということです。
※App Checkだけに頼るのではなく、しっかりした情報管理と認証設計を意識してアプリケーションを作りましょう!

App Checkはどうやって不正アクセスを検知するのか

App Checkは以下のいずれかもしくは両方の条件を満たしているかを把握してアクセスの可否を判断します。

1. リクエストは本物のアプリから発信されます
2. リクエストは、改ざんされていない正規のデバイスから発信されます

1はFirebaseに登録しているアプリから来たリクエストであることをチェックするということですが、Webアプリの場合、リクエストのオリジンがFirebase Hostingに登録されているものかどうかを判定します。

2はアプリの種類によって手法と利用される技術は異なりますが、アプリケーションはボットじゃないかどうかを判定するのです。Webアプリの場合は、reCAPTCHA v3の技術を利用して機能を実現しています。

事前準備

本記事は読者が追ってコーディングができるように作成しています。

今回は、ゼロからではなく、既にあるFirebaseアプリケーションにApp Checkを組みこますので、前回の記事、FirebaseのCloud Firestoreでページネーションを実装する方法で作ったブログアプリケーションを使います。

https://github.com/tronicboy1/angular-firebase-blog/releases/tag/1.0

また、上記のソースコードの他にFirebaseのプロジェクトが既に作成してある前提で進めます。
もし、Firebaseプロジェクトをまだお作りでない場合、こちらの説明に従って作っていただければと思います。
また、前の記事(FirebaseのCloud Firestoreでページネーションを実装する方法の記事リンク)をお読みいただければ、上記のソースコードの細かい説明もあるのでご興味あればぜひ!

App Checkを有効にする

事前準備が整ったら、早速始めましょう!
最初にしなければならないのは、FirebaseコンソールでApp Checkを有効にすることです。
まず、Firebaseコンソール(https://console.firebase.google.com/)にログインしてプロジェクトを選択してください。
ダッシュボードの左側のメニューからApp Checkを選んでクリックしましょう。

App Checkのホーム画面で色々と説明がありますので、もしよければ動画を見ていただけれApp Checkの性能をより詳しく理解していただけるかと思います。
とりあえず、準備ができたら、始めるのボタンをクリックします。

次のページで対象のアプリ、今回はwebという名前のWebアプリケーションを使いますが、登録ボタンをクリックします。

次、reCAPTCHAかreCAPTCHA Enterpriseを問われますが、reCAPTCHAを選びましょう。

このページはそのままにして、新しいタブでこちらのGoogle reCAPTCHA v3コンソール(https://www.google.com/recaptcha/admin/create)を開きましょう。

ラベルとタイプは以下のように入力します。

ドメインは以下のようにFirebase Hostingで用意されているデフォルトのURL、もしくは登録したカスタムドメインを入力します。
※ https://などのプロトコルを含めるとエラーになります

HostingのURLがわからない場合

Firebaseコンソール(https://console.firebase.google.com/)から簡単に確認できます。

ドメインの入力ができたら、最後に自分以外の管理者がいる場合、オーナーに登録します。
それから、利用条件をご確認の上、同意し、送信ボタンをクリックします。

登録が無事にできたら、以下のような画面が表示され、FirebaseコンソールのApp Check登録画面に必要な情報をコピーできます。

上記の登録結果画面のシークレットキーをコピーしてから、Firebaseコンソールのタブに戻ってreCAPTCHA秘密鍵に貼り付けます。
トークンの有効期限は初期値にしますが、reCAPTCHAのテストをどれくらいの頻度で実行するか設定できます。
保存ボタンをクリックして登録してみましょう。

すると以下のように、登録が無事に完了したらreCAPTCHAに緑色のチェックが入ります!OKです。

WebアプリケーションにApp Checkの機能を追加する

プロジェクト設定の準備ができたので、次はアプリケーションにreCAPTCHAのテストを実行するためのソースコードを追加します。

こちらの正式ドキュメント(https://firebase.google.com/docs/app-check/web/recaptcha-provider?authuser=0&hl=ja)に従って進んでいきましょう!

まず、src/firebase/にapp-check-module.tsを追加して以下のようなロジックを追加します。
※ app-check.tsという名前にするとnode_modulesの中に入っているfirebase/app-checkとコンフリクトするので名前を分けておくか、これをsrc/firebase/index.tsの中に入れるかです。

import { initializeAppCheck, ReCaptchaV3Provider } from "firebase/app-check";
import { firebaseApp } from "./index";

const reCAPTCHA_PUBLIC_KEY = "6LfZi5UiAAAAAA9IqaPiw_C-wn17mziJTJWduHZX";

export const startAppCheck = () => initializeAppCheck(firebaseApp, {
  provider: new ReCaptchaV3Provider(reCAPTCHA_PUBLIC_KEY),
  isTokenAutoRefreshEnabled: true,
});

reCAPTCHA_PUBLIC_KEYの値は、先ほどのreCAPTCHA Adminコンソールで出ていた上の方の鍵です。

次は、src/app/app.component.ts(https://github.com/tronicboy1/angular-firebase-blog/blob/main/src/app/app.component.ts)に入って、上記で作った関数startAppCheckをインポートしてngAfterViewInitのライフサイクル・コールバック関数(https://angular.io/guide/lifecycle-hooks)で実行します。

import { Component } from "@angular/core";
import { startAppCheck } from "@firebase/app-check-module";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})
export class AppComponent {
  ngAfterViewInit(): void {
    startAppCheck();
  }
}

デプロイしてみる

準備ができたので、新しいソースコードをビルドしてFirebase Hostingにデプロイしましょう。

ng build
firebase deploy

デプロイが終われば、Firebase HostingのURLを開きます。

一件何も変わっていないように見えますが、Devツールで調べてみましょう。

DevツールでDOMツリーを見ると、fire_app_check_[DEFAULT]というid属性を持った<div>要素が<body>要素にこっそりとレンダーされていることがわかります。
ページを更新してこの<div>要素の動きを見てみましょう。

やはり何らかの動きが自動的に起きているようです。これはきっとApp Checkなのでしょう!

Dev環境でもアクセスできるようにする

本番環境で作動しているのでよし!と思った読者、トトトトトトッ!ちょっと待った!
Dev環境で開いてみましょう。

ng serve

開いてみると(http://localhost:4200/)、アキサミヨー!

App CheckのせいでDev環境が繋がらなくなったのです。
これを解決していきますが、この資料(https://firebase.google.com/docs/app-check/web/debug-provider?authuser=0&hl=ja)を参考にします。

Webアプリケーションのコードを修正する

まずは、Dev環境の時にデバッグトークンというものをブラウザのコンソールに出力するようにコードを修正します。
src/firebase/app-check-module.tsに戻って以下のように修正します。

import { initializeAppCheck, ReCaptchaV3Provider } from "firebase/app-check";
import { firebaseApp } from "./index";
import { environment } from "../environments/environment";

const reCAPTCHA_PUBLIC_KEY = "6LfZi5UiAAAAAA9IqaPiw_C-wn17mziJTJWduHZX";

if (!environment.production) {
  self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
}

export const startAppCheck = () =>
  initializeAppCheck(firebaseApp, {
    provider: new ReCaptchaV3Provider(reCAPTCHA_PUBLIC_KEY),
    isTokenAutoRefreshEnabled: true,
  });

declare var self: {
  FIREBASE_APPCHECK_DEBUG_TOKEN: boolean | undefined;
};

import { environment } from “../environments/environment”;ですが、こちらはAngular特有の書き方で、Angularの環境変数を利用するためのことです。AngularでないアプリケーションではDev環境かどうかを判定するための環境変数を参照すればいいです。

また、TypeScriptに関する問題ですが、こちらの資料(https://firebase.google.com/docs/app-check/web/debug-provider?authuser=0&hl=ja)の説明通りではTypeScriptのインタプリーターが文句を言ってくるので、declare var selfでselfの定義をすればTypeScriptのエラーを回避できます。
※最も簡単なやり方は//@ts-ignoreなのですが、ESLint等の設定によりこれがまた引っかかることがあるでしょうから、筆者はちゃんとしましょうね。

上記の変更を保存してDevサーバーを開いてDevツールのコンソール出力をみると、デバッグトークンがログされていることがわかります。

これは後ほど使うのでコピーしておいてください。

FirebaseのApp Checkにデバッグトークンを登録する

次は、Firebaseコンソール(https://console.firebase.google.com/)に戻ってApp Checkの設定を開いて、アプリのタブをクリックします。
そして前回と同じwebですが、こちらの縦に並んでいる三つの点をクリックします。

続いて「デバッグトークンを管理」をクリックします。

そして次に、「デバッグトークン」を追加をクリックします。

ここに、トークンを出したパソコンの名称を書いて、上記でコピーしたデバッグトークンを入れます。

入力が終わったら保存ボタンをクリックします。これでデバッグトークンの登録は完了でOK!
localhost:4200に戻ると、App Checkを導入する前と同じようにアクセスできていることが確認できます。

本来であれば、Firebase Local Emulator Suite(https://firebase.google.com/docs/emulator-suite)を使ってFirebaseの外部サービスへアクセスすることもないのですが、場合によってはこのような対応も必要かと思いますので、追記しておきました。

まとめ

ここまでFirebase App Checkの便利な不正アクセス防止ツールを紹介してきましたが、いかがでしょうか?
不正アクセス、ボットによるデータマイニング等、猫の手を借りてでも阻止したいという話をよく聞きます。
繰り返しになりますが、App Checkだけに頼るのは間違いですが、Firebaseもこのようなサービスを提供してくれるおかげで個人で出すようなアプリケーションでもGoogle基準のボット対策ができるという事実に僕は感動しました。
もちろん、App CheckでなくともreCAPTCHAは使えますが、なかなかこのように円滑に組み込めることはないでしょう。
Firebaseの熱、感じていますか?

井上オースティンことAustin John Mayerより

こちら(https://github.com/tronicboy1/angular-firebase-blog/releases/tag/1.1)で最終的なソースコードを確認することができます。