Closed4
Firebase App Check × reCAPTCHA Enterprise の仕組み

Firebase App Check を Web アプリで使うとき、reCAPTCHA Enterprise プロバイダを選ぶと、ユーザーに対して追加の操作(チェックボックスや画像選択など)を強いることなく、裏側で自動的にアクセス元の信頼性を評価することができる。
裏で何が起きているのか気になって調べたのでメモしておく。

Firebase App Check の使い方(Web)
Firebase App Checkは、Firebaseのバックエンド(Firestore, Storage, Functions)や独自のバックエンドをボットなどから守るためのもの。
導入ステップ(Web)
import { initializeApp } from "firebase/app";
import { initializeAppCheck, ReCaptchaEnterpriseProvider } from "firebase/app-check";
const app = initializeApp({ /* Firebase 設定 */ });
initializeAppCheck(app, {
provider: new ReCaptchaEnterpriseProvider("your-site-key"),
isTokenAutoRefreshEnabled: true,
});
-
isTokenAutoRefreshEnabled: true
をつけておくと、SDK が内部でトークンの更新を管理してくれる - Firebase SDK を通じた通信には、自動で X-Firebase-AppCheck ヘッダが付与される
トークンの扱い
- App Check トークンは JWT 形式、TTL はデフォルトで 1 時間
- TTL の半分(30 分)を超えると、自動で更新処理が走る
参考

明示的にトークンを取得したいとき
独自のバックエンドでreCAPTCHA Enterpriseの認証を行う場合、Firebase SDK を介さない fetch や SWR のようなライブラリを使って通信することになるため、自分でトークンを取得してヘッダに付ける必要がある。
import { getToken } from "firebase/app-check";
const token = await getToken(appCheck, /* forceRefresh= */ false);
バックエンド側でトークンの認証を独自に行う。
useSWR で fetcher にトークンを入れる例
import useSWR from 'swr';
import { getToken } from 'firebase/app-check';
const fetchWithAppCheck = async (url: string) => {
const { token } = await getToken(appCheck, false);
const res = await fetch(url, {
headers: {
'X-Firebase-AppCheck': token,
},
});
if (!res.ok) throw new Error("Request failed");
return res.json();
};
const { data, error } = useSWR('/api/data', fetchWithAppCheck);

reCAPTCHA Enterprise のトークン発行の仕組み
reCAPTCHA Enterpriseでは、ページに以下のスクリプトが読み込まれる。
<script src="https://www.google.com/recaptcha/enterprise.js?render=your-site-key"></script>
これにより、
- User-Agent や画面サイズなどのパッシブシグナルを収集
- mousemove / click / keydown / scroll などのアクティブシグナルを監視
を行う。
トークン発行の流れ
grecaptcha.enterprise.ready(() => {
grecaptcha.enterprise.execute("your-site-key", { action: "login" })
.then(token => {
// この token をサーバーに送るなど
});
});
この execute() の中で
- これまでバッファされたシグナルをまとめて暗号化
- Invisible iframe 経由で Google に送信
- リスクスコアの判定がされる
- 暗号化トークン(有効期限 ≒ 2 分)が返ってくる
が実行される。
このトークンは、アクションごとに使い捨て(stateless)で、2 分以内に使う必要がある。
参考
このスクラップは4ヶ月前にクローズされました