Firebaseの新機能App Checkで乱用されるのを防ぐ

2021/05/19に公開

日本時間の2021/05/19からGoogle I/Oが開催されていますが、それに伴ってFirebaseにも新しい機能が追加されています。その中の App Check という新機能がよさそうだったのでドキュメントを読んでまとめてみました。

ドキュメントと動画は👇
https://firebase.google.com/docs/app-check
https://www.youtube.com/watch?v=Fjj4fmr2t04

App Checkとは

みなさんのサービスで利用されているFirebaseのバックエンドサービスの不正利用を防ぐための機能です。信頼できるクライアントからのリクエストの割合を見ることができ、状況に応じて信頼できるクライアントからのリクエストのみを受け付けるように強制できます。

クライアントが信頼できるどうかは、ドキュメント内ではattestationと呼ばれていますが、このattestationのプロバイダーはプラットフォームごとに異なります。

これらのプロバイダーが提供する情報を活用して、App Checkはクライアントのリクエストが信頼できるものなのかを判別します。そのため、セキュリティの強さはプロバイダー次第だそうです。また、サードパーティーのプロバイダーも利用できるみたいですが今回は割愛します。

今日現在で対応されているFirebaseのサービスは以下の3つです。

  • Realtime Database
  • Cloud Storage
  • Cloud Functions(Callable)

「今後対応サービスはすぐ追加するから!」ってブログの中で言ってるので期待して待ちましょう。Firestoreが対応されるのが楽しみです。

※ 追記 2021/11/11

Firebase Summit 2021で対応サービスの追加が発表されました。

  • Firestore
  • Custom Backend Resources

導入方法

いずれのプラットフォームでも簡単そうです。例えばWebの場合、

  1. reCAPTCHA v3のキーを発行
  2. import 'firebase/app-check'
  3. firebase.initializeApp() 後に firebase.appCheck().activate('YOUR_PUBLIC_KEY') を呼ぶ

だけでいいようです。

リクエストのメトリクスのEnforcement

導入後しばらくすると、Realtime DatabaseとCloud Storageのリクエストメトリクスが以下のように見れるようになるそうです(画像はこちらより転載)。

ちなみに、Cloud Functionsの場合は自動的に以下のようなログが出力されるようなので、自分でCloud Loggingなどを使ってフィルターして見てくれとのことでした。

{
  "severity": "INFO",    // INFO, WARNING, or ERROR
  "logging.googleapis.com/labels": {"firebase-log-type": "callable-request-verification"},
  "jsonPayload": {
    "message": "Callable header verifications passed.",
    "verifications": {
      // ...
      "app": "MISSING",  // VALID, INVALID, or MISSING
    }
  }
}

リクエストが4つに分類されます。Verified以外はすべてUnverifiedとして扱われるようです。

  • Verified
  • Outdated client(Unverified)
    • App CheckのトークンなしでSDKを使ってリクエストしていている。おそらく古いSDKバージョンでの利用。
  • Unknown origin(Unverified)
    • App Checkトークンがなく、SDKからのリクエストでもなさそう
  • Malicious(Unverified)
    • 不正なApp Checkトークンでのリクエスト

メトリクスの状況を見て、Verifiedなリクエストのみを受け付けるように設定することができます。これをドキュメントではEnforcementと呼んでいました。導入するだけではEnforcementが有効になるわけではないのでひとまず導入だけでもしてみるのはいいかもしれません。

Enforcementを有効にするタイミングもドキュメントにガイドライン例として記載されていました。

  • ほとんどのリクエストがVerifiedなら有効にすることを考慮する
  • Outdatedなリクエストが多そうだったらもうちょっと待つ(有効にしたら古いSDKバージョンのユーザーが壊れちゃう)
  • まだリリースしてないサービスなら有効にすべき

Enforcementを有効にするには、Realtime Database, CloudStorageはコンソールから有効にすればよいです。Cloud Functionsの場合は、コードを修正する必要があります。詳細はこちらをご確認下さい。

exports.yourCallableFunction = functions.https.onCall((data, context) => {
  // context.app will be undefined if the request doesn't include a valid
  // App Check token.
  if (context.app == undefined) {
    throw new functions.https.HttpsError(
        'failed-precondition',
        'The function must be called from an App Check verified app.')
  }
  // Your function logic follows.
});

注意すること

おわりに

これは非常に強力な機能なのではないでしょうか。自分たちのバックエンドサーバーを通すことなくリクエストするFirebaseの性質にあった機能であり、可能な限り有効にすべき機能に見えます。僕が開発しているサービスでも早速有効にしてみたいのですが、RealtimeDBがGCSをヘビーユースしているサービスがないので意味のあるメトリクスが見れるかは少し微妙なところです。

今後の進化も楽しみですね!

https://twitter.com/_mogaming/status/1394808505568096258?s=21

Discussion