google-services 4.6.0でApp Checkのデバッグトークンをデバッグビルドに自動で入れる|firebase-appcheck.jsonの置き場所と、トークンが入らない条件

google-services 4.6.0は、App Checkのデバッグトークンをデバッグビルドに入れる

Firebaseが2026年11月11日に、Android向けのFirebase BoM 35.2.0と、google-services Gradleプラグイン4.6.0を公開しました(FirebaseのAndroid向けリリースノート)。google-servicesプラグインは、google-services.jsonに書かれたプロジェクトの情報を、アプリのリソース(R.stringの文字列)に変換するGradleプラグインです。4.6.0では、App Checkのデバッグトークンをfirebase-appcheck.jsonというファイルから読み、デバッグビルドのリソースに入れるようになりました。

App Checkは、Firebaseのサービスへのリクエストが、登録した本物のアプリから届いたかを確かめる仕組みです。エミュレーターや開発中の端末のアプリはこの判定を通らないため、Firebaseのコンソールに登録した「デバッグトークン」(開発用の秘密の文字列)を使います。Firebase AI Logicでは、2026年11月2日からApp Checkの自動適用が始まりました(プロジェクトごとに一時的に延期できます。詳しくはFirebase AI LogicのApp Checkは11月2日から必須に)。

これまでは、アプリを一度起動してログに出たトークンをコピーし、コンソールで登録していました。同じ11月11日の更新に含まれるFirebase CLI 15.36.0では、firebase appcheck:debugtokens:createがトークンを登録して手元のファイルに保存します(Firebase CLI 15.36.0のリリースノート)。google-servicesプラグイン4.6.0がそのファイルを読んでトークンをデバッグビルドに入れ、App Check Debug 20.1.0のライブラリがそのトークンを使います。

この記事では、google-servicesプラグインの4.5.0と4.6.0を、ダミーのgoogle-services.jsonを置いた同じ最小アプリで比べました。トークンが入る条件と入らない条件、アプリがどのトークンを使うか(Androidエミュレーターで確認)、同時に消えたreCAPTCHAのサイトキーの扱い、デバッグビルドを扱うときの注意を順に説明します。

要点

登録したデバッグトークンが、デバッグビルドにだけ自動で入る

google-servicesプラグイン4.5.0と4.6.0に、同じ設定のアプリを渡して比べた結果です。

トークンが入る場所

デバッグビルドのR.string.firebase_app_check_debug_token

isDebuggableがtrueのビルドの種類だけに入り、リリースビルドには入りませんでした。4.5.0はどちらにも入れません。

アプリ側

App Check Debug 20.1.0がリソースのトークンを使う

リリースビルドに入れたトークンは、ライブラリが無視しました。

入らないとき

ビルドはそのまま成功し、アプリは別のトークンを使う

アプリIDの書き間違いや、使えない文字を含むトークンで起きました。アプリは端末に保存済みのトークンか、新しく作ったトークンを使います。

同時の変更

recaptcha_site_keyのリソースを作らなくなった

R.string.recaptcha_site_keyを読むコードは、4.6.0でコンパイルエラーになりました。

firebase-appcheck.jsonは、アプリIDごとにトークンを持つ

google-servicesプラグイン4.6.0が読むfirebase-appcheck.jsonは、tokensの中に「アプリID: トークン」の組を並べたJSONです。アプリIDはgoogle-services.jsonのmobilesdk_app_idの値で、1:123456789012:android:0123456789abcdefのような形をしています。検証では、次のファイルを作りました(トークンはダミーの値です)。

{
  "tokens": {
    "1:123456789012:android:0123456789abcdef": "11111111-2222-4333-8444-555555555555"
  }
}

Firebase CLI 15.36.0のソースでは、firebase appcheck:debugtokens:createが作ったトークンを、このファイルに_comment(ファイルに秘密が入っていることを示す注記)とtokenNames(Firebaseに登録したトークンを指すリソース名)を添えて書き、ファイルの権限を所有者だけが読み書きできる600にします(src/appcheck/localConfig.ts)。保存したくない場合は--no-save-localを付けます。

プラグインがファイルを探す場所は、次の順です(GoogleServicesPlugin.kt)。手元では、1と3の2通りでトークンが入ることを確かめました。

google-services 4.6.0がfirebase-appcheck.jsonを探す順

1. Gradleのプロパティで指定したファイル

-Pfirebase.appcheck.configFile=/path/to/firebase-appcheck.jsonのように指定すると、このファイルだけを読みます。同じ名前のシステムプロパティでも指定できます。

2. ホームフォルダーのconfigstore

~/.config/configstore/firebase-appcheck.json。Firebase CLIが書く場所です。

3. XDG_CONFIG_HOMEの下のconfigstore

環境変数XDG_CONFIG_HOMEがあれば、$XDG_CONFIG_HOME/configstore/firebase-appcheck.jsonも探します。

プラグインの書き方は4.5.0までと同じです。ルートのbuild.gradle.ktsで版を4.6.0にし、アプリのモジュールで適用します。

// ルートの build.gradle.kts
plugins {
    id("com.android.application") version "9.5.1" apply false
    id("com.google.gms.google-services") version "4.6.0" apply false
}

// app/build.gradle.kts
plugins {
    id("com.android.application")
    id("com.google.gms.google-services")
}

この状態でビルドすると、デバッグビルド用に生成されるapp/build/generated/res/processDebugGoogleServices/values/values.xmlにだけ、トークンの行が入りました。リリース用のprocessReleaseGoogleServicesのファイルには入りません。

プラグインがトークンを入れるかどうかは、ビルドの種類(buildType)のisDebuggableで決まります(取れない場合は名前がdebugかどうか)。isDebuggable = trueにしたstagingというビルドの種類を足して試すと、そちらにもトークンが入りました。この記事の「デバッグビルド」は、isDebuggableがtrueのビルドを指します。

<!-- processDebugGoogleServices/values/values.xml(4.6.0、一部) -->
<string name="firebase_app_check_debug_token" translatable="false">11111111-2222-4333-8444-555555555555</string>
<string name="gcm_defaultSenderId" translatable="false">123456789012</string>
<string name="google_app_id" translatable="false">1:123456789012:android:0123456789abcdef</string>

トークンが入ったかは、Gradleを--info --rerun-tasks付きで実行すると分かります。入ったときだけ、Injecting Firebase App Check debug token for app 1:123456789012:android:0123456789abcdef from <読んだファイルのパス>の行が出ました。同じファイルを4.5.0に渡すと、この行は出ず、トークンも入りません。--rerun-tasksを付けずに続けて実行すると、タスクがUP-TO-DATE(前回の結果を使い回した状態)になり、トークンが入っていてもこの行は出ませんでした。

App Check Debug 20.1.0は、保存済みのトークンよりリソースを優先する

リソースに入ったトークンは、App Checkのデバッグ用ライブラリfirebase-appcheck-debugの20.1.0(Firebase BoM 35.2.0に含まれる版)が使います。アプリのコードは、デバッグ用のプロバイダーを登録する従来の形のままです。検証に使ったアプリでは、起動時に次のコードを実行しました。

FirebaseApp.initializeApp(this);
FirebaseAppCheck appCheck = FirebaseAppCheck.getInstance();
appCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance());
appCheck.getAppCheckToken(false);

アプリでは、Firebaseのドキュメントのとおり、デバッグ用のプロバイダーをデバッグビルドだけで登録します。検証用のアプリは、リリースビルドでの動きも見るために条件を付けずに登録しました。

Androidエミュレーター(Android 15、機内モードでネットワークを切った状態)で3種類のAPKを動かし、ログを比べました。

トークンを入れたデバッグビルド

入れたトークンを使った

Debug token loaded from R.string.firebase_app_check_debug_token.のあと、firebase-appcheck.jsonと同じトークンが表示されました。

トークンを入れていないデバッグビルド

新しいトークンを作った

インストールしたばかりで、保存済みのトークンがない状態です。Debug token loaded from auto-generated UUID.と、作ったトークンの登録方法が出ました。

リリースビルドにトークンを手で入れた場合

トークンを無視した

SECURITY WARNING: App Check debug token found in a non-debuggable Release build! Ignoring token.のあと、新しいトークンを作りました。

3つ目は、プラグインに頼らずリリースビルドのresValueで同じ名前の文字列を入れ、デバッグ用のプロバイダーを登録したまま動かした結果です(AGP 9.5.1ではbuildFeatures { resValues = true }も必要でした)。ライブラリの処理をjavapで読むと、トークンを決める順は、テスト用に渡すトークン(InternalDebugSecretProvider)、R.string.firebase_app_check_debug_token、端末に保存済みのトークン、新しく作るトークン、の順でした。リソースの値は、デバッグできる(debuggable)ビルドのときだけ使われます。

トークンを入れたビルドでも、ログには登録方法の案内が続けて出ます。firebase appcheck:debugtokens:create <トークン> --project <プロジェクトID> --app <アプリID>の形で、表示されたトークンを登録するコマンドが示されます。CLIで作って登録したトークンなら、この案内のとおりに登録し直す必要はありません。

トークンが入らない4つの場合も、ビルドは成功する

4.6.0でトークンが入らなかった場合は、どれもビルドが成功し、トークンについての警告も出ませんでした。アプリは、端末に保存済みのトークンがあればそれを使い、なければ新しいトークンを作ります。以前に登録したトークンが端末に残っていると、注入に失敗してもApp Checkを通ることがあり、失敗に気づきにくくなります。手元で試した4つの場合をまとめます。

入らなかった場合 1

探す場所のどこにもファイルがない

確かめる箇所

CLIを実行したユーザーと、Gradleを動かすユーザー(ホームフォルダー)が同じか。-Pfirebase.appcheck.configFileで指定したパスが正しいか

入らなかった場合 2

tokensのキーのアプリIDが、ビルドするアプリと違う

確かめる箇所

キーがgoogle-services.jsonのmobilesdk_app_idと同じか。ビルドの種類やフレーバーごとに別のアプリIDを使っていないか

入らなかった場合 3

トークンに<などの文字が入っている、または@で始まる

確かめる箇所

プラグインは<>&"'を含む値と、@・?で始まる値を使いません。CLIが作るUUIDの形にします

入らなかった場合 4

isDebuggableがfalseのビルド(リリースビルドなど)

確かめる箇所

仕様どおりの動きです。isDebuggableがtrueのビルドの種類だけに入ります

入らない原因を調べるときは、./gradlew :app:processDebugGoogleServices --info --rerun-tasksの出力でInjecting Firebase App Check debug tokenの行を探し、生成されたvalues.xmlにfirebase_app_check_debug_tokenの行があるかを見ます。アプリ側では、ログのDebug token loaded fromのあとがR.string.firebase_app_check_debug_tokenになっているかを確かめます。

4.6.0は、reCAPTCHAのサイトキーをリソースにしない

4.6.0では、google-services.jsonのreCAPTCHAのサイトキーを処理しなくなりました(リリースノート)。google-services.jsonのclientにrecaptcha_site_keyを入れて比べると、4.5.0はデバッグとリリースの両方にrecaptcha_site_keyの文字列リソースを作り、4.6.0はどちらにも作りませんでした。

R.string.recaptcha_site_keyを読むクラスを足してコンパイルすると、4.5.0は成功し、4.6.0は次のエラーで止まりました(JDKの表示言語が日本語の環境での表示です)。

SiteKey.java:7: エラー: シンボルを見つけられません
        return context.getString(R.string.recaptcha_site_key);
                                         ^
  シンボル:   変数 recaptcha_site_key

上げる前に、アプリのコードと設定でrecaptcha_site_keyを検索します。参照があれば、サイトキーを自分のリソースや設定に移してから4.6.0に上げます。

デバッグビルドのAPKとログには、トークンがそのまま入る

トークンを入れたデバッグビルドのAPKをaapt2 dump resourcesで見ると、string/firebase_app_check_debug_tokenの値として、トークンがそのまま入っていました。トークンを入れていないAPKでは、同じ名前のリソースが空の文字列でした(firebase-appcheck-debugが空の値を持っているため)。ログにも、起動のたびにトークンが表示されます。

デバッグトークンは、登録したプロジェクトのApp Checkを通るための秘密の値です。トークンを入れたデバッグビルドのAPKを、チームの外へ配布する経路(テスト配布のサービスやファイル共有)に載せないようにします。isDebuggableをtrueにしたstagingなどのビルドにも入るため、テスターに配るビルドの種類も確かめます。使わなくなったトークンはfirebase appcheck:debugtokens:deleteで取り消し、手元のファイルに残った古いトークンはfirebase appcheck:debugtokens:pruneで整理できます(pruneはCLI 15.36.0で追加)。

CIでビルドする場合は、firebase-appcheck.jsonをリポジトリに入れず、CIの秘密情報として置いたファイルを-Pfirebase.appcheck.configFile=で指定できます。手元の検証でも、作業フォルダーのファイルをこのプロパティで指定してトークンが入りました。この方法では、CIで作ったAPKにもトークンが入ります。CIのために別のトークンを作るときは、自分のパソコンのファイルを書き換えないよう、CLIに--no-save-localを付けます。計測テストだけでトークンを使う場合は、Firebaseのドキュメントにある、テストの引数でトークンを渡す方法も選べます。

4.6.0へ上げるときに確かめる3つのこと

上げる前の確認

1. プラグインとライブラリを両方上げたか

トークンを入れるのはgoogle-servicesプラグイン4.6.0、使うのはfirebase-appcheck-debug 20.1.0(BoM 35.2.0)です。手元で調べた20.0.0のライブラリには、このリソースを読む処理がありませんでした。

2. recaptcha_site_keyを参照していないか

4.6.0ではリソースが作られず、参照するコードはコンパイルエラーになります。

3. トークン入りのビルドを配る経路がないか

トークンは、isDebuggableがtrueのビルドのAPKに文字列リソースとして入ります。そうしたビルドを外部へ配る仕組みがあれば、トークンを入れずにビルドする手順を分けます。

google-servicesプラグイン4.6.0とApp Check Debug 20.1.0を使うと、CLIで作って登録したトークンが、デバッグビルドのたびに自動で入ります。エミュレーターを作り直すたびにログからトークンをコピーして登録する作業がなくなり、チームの各自がCLIで自分のトークンを作れば、リポジトリに秘密の値を置かずに済みます。

参考資料

検証環境

  • macOS 27.0.1(Apple Silicon)、Gradle 9.9.0、Android Gradle Plugin 9.5.1
  • google-services Gradleプラグイン4.5.0と4.6.0、Firebase BoM 35.2.0(firebase-appcheck-debug 20.1.0)
  • Android Emulator 36.3.10(Android 15)
  • 検証日: 2026年11月14日

この記事は、AIが調査と下書きを担当し、上記の環境で実際に動かして結果を確かめ、下書きとは別の担当が公開前に本文と出典を確認しています。制作と訂正の方針は編集・訂正方針で公開しています。