Apple プラットフォーム向け Firebase App Check

1. はじめに

Firebase App Check は、正当なアプリやデバイスからのリクエストであることを確認することで、請求詐欺やフィッシングなどの不正行為からバックエンド リソースを保護します。Firebase サービスとお客様独自のバックエンド サービスの両方と連携して、リソースを安全に保ちます。

Firebase App Check について詳しくは、Firebase のドキュメントをご覧ください。

App Check は、プラットフォーム固有のサービスを使用して、アプリやデバイスの完全性を検証します。これらのサービスは証明書プロバイダと呼ばれます。そのようなプロバイダの 1 つが Apple の App Attest サービスです。App Check はこのサービスを使用して、Apple のアプリとデバイスの真正性を検証します。

作成するアプリの概要

この Codelab では、既存のサンプル アプリケーションに App Check を追加して適用し、プロジェクトの Realtime Database が不正なアプリやデバイスからアクセスされないように保護します。

ラボの内容

  • Firebase App Check を既存のアプリに追加する方法
  • さまざまな Firebase App Check 証明書プロバイダをインストールする方法。
  • アプリに App Attest を構成する方法
  • アプリ開発中にシミュレータでアプリをテストするようにデバッグ証明書プロバイダを構成する方法。

必要なもの

  • Xcode 13.3.1 以降
  • 新しいアプリ ID を作成できる Apple Developer アカウント
  • App Attest をサポートする iOS/iPadOS デバイス(App Attest API の提供状況をご覧ください)

2. スターター プロジェクトを取得する

iOS 用の Firebase クイックスタート リポジトリには、さまざまな Firebase プロダクトのデモを行うためのサンプルアプリが含まれています。この Codelab のベースとして、SwiftUI 用の Firebase Database クイックスタート アプリを使用します。

コマンドラインから iOS 用の Firebase クイックスタート リポジトリのクローンを作成します。

git clone https://github.com/firebase/quickstart-ios.git
cd quickstart-ios

Xcode で Realtime Database SwiftUI クイックスタート アプリ プロジェクトを開きます。

cd database/DatabaseExampleSwiftUI/DatabaseExample
xed .

3. アプリに App Check を追加する

  1. Swift Package Manager によってプロジェクトの依存関係が解決されるのを待ちます。
  2. DatabaseExample (iOS) アプリ ターゲットの [General] タブを開きます。次に、[Frameworks, Libraries, and Embedded Content] セクションで、[+] ボタンをクリックします。
  3. 選択して FirebaseAppCheck を追加します。

4. App Check プロバイダ ファクトリを作成してインストールする

  1. Shared ファイル グループに、AppCheck という名前の新しいグループを追加します。
  2. このグループ内で、別ファイル(MyAppCheckProviderFactory.swift など)でファクトリ クラスを作成し、DatabaseExample (iOS) ターゲットに追加します。
    import Firebase
    
    class MyAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
      func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
        #if targetEnvironment(simulator)
          // App Attest is not available on simulators.
          // Use a debug provider.
          return AppCheckDebugProvider(app: app)
        #else
          // Use App Attest provider on real devices.
          return AppAttestProvider(app: app)
        #endif
      }
    }
    
  3. 次に、DatabaseExampleApp.swiftFirebaseAppCheck をインポートし、MyAppCheckProviderFactory クラスのインスタンスを App Check プロバイダ ファクトリとして設定します。
    import SwiftUI
    import FirebaseCore
    import FirebaseAppCheck
    
    @main
    struct DatabaseExampleApp: App {
      init() {
        // Set an instance of MyAppCheckProviderFactory as an App Check
        // provider factory before configuring Firebase.
        AppCheck.setAppCheckProviderFactory(MyAppCheckProviderFactory())
        FirebaseApp.configure()
      }
      ...
    }
    

5. Firebase プロジェクトを作成して構成する

iOS プロジェクトで App Check を使用するには、Firebase コンソールで次の手順を実施する必要があります。

  • Firebase プロジェクトを設定します。
  • iOS アプリを Firebase プロジェクトに追加します。
  • Firebase Authentication を構成する。
  • 保護する Realtime Database インスタンスを初期化します。
  • App Check を構成します。

プロジェクトを作成する

まず、Firebase プロジェクトを作成する必要があります。

  1. Firebase コンソールで [プロジェクトを追加] を選択します。
  2. プロジェクトに App Check Codelab という名前を付けます。
  3. [続行] をクリックします。
  4. このプロジェクトの Google アナリティクスを無効にして、[プロジェクトを作成] をクリックします。

Realtime Database インスタンスを作成する

次に、Firebase コンソールの [Realtime Database] セクションに移動します。

  1. [データベースを作成] ボタンをクリックして、データベース作成ワークフローを開始します。
  2. データベースのデフォルトの場所(us-central1)は変更せずに、[次へ] をクリックします。
  3. [ロックモード] が選択されていることを確認し、[有効にする] ボタンをクリックしてデータベースのセキュリティ ルールを有効にします。
  4. Realtime Database ブラウザの [Rules] タブに移動し、デフォルトのルールを次のように置き換えます。
    {
        "rules": {
            // User profiles are only readable/writable by the user who owns it
            "users": {
                "$UID": {
                    ".read": "auth.uid == $UID",
                    ".write": "auth.uid == $UID"
                }
            },
            // Posts can be read by anyone but only written by logged-in users.
            "posts": {
                ".read": true,
                ".write": "auth.uid != null",
                "$POSTID": {
                    // UID must match logged in user and is fixed once set
                    "uid": {
                        ".validate": "(data.exists() && data.val() == newData.val()) || newData.val() == auth.uid"
                    },
                    // User can only update own stars
                    "stars": {
                        "$UID": {
                            ".validate": "auth.uid == $UID"
                        }
                    }
                }
            },
            // User posts can be read by anyone but only written by the user that owns it,
            // and with a matching UID
            "user-posts": {
                ".read": true,
                "$UID": {
                    "$POSTID": {
                        ".write": "auth.uid == $UID",
                        ".validate": "data.exists() || newData.child('uid').val() == auth.uid"
                    }
                }
            },
            // Comments can be read by anyone but only written by a logged in user
            "post-comments": {
                ".read": true,
                ".write": "auth.uid != null",
                "$POSTID": {
                    "$COMMENTID": {
                        // UID must match logged in user and is fixed once set
                        "uid": {
                            ".validate": "(data.exists() && data.val() == newData.val()) || newData.val() == auth.uid"
                        }
                    }
                }
            }
        }
    }
    
  5. [公開] ボタンをクリックして、更新したセキュリティ ルールを有効にします。

Firebase に接続できるように iOS アプリを準備する

実機でサンプルアプリを実行できるようにするには、Xcode が必要なプロビジョニング プロファイルを管理できるように、開発チームにプロジェクトを追加する必要があります。サンプルアプリをデベロッパー アカウントに追加する手順は次のとおりです。

  1. Xcode で、プロジェクト ナビゲータの DatabaseExample プロジェクトを選択します。
  2. DatabaseExample (iOS) ターゲットを選択し、[Signing & Capabilities] タブを開きます。
  3. 「Signing for DatabaseExample (iOS) require a development team」というエラー メッセージが表示されます。
  4. バンドル ID を一意の識別子に更新します。最も簡単な方法は、ウェブサイトのリバース ドメイン名(例: com.acme.samples.firebase.quickstart.DatabaseExample)を使用する方法です(この ID は使用せず、独自の一意の ID を使用してください)。
  5. 開発チームを選択します。
  6. Xcode で「Provisioning Profile: Xcode Managed Profile」と表示され、このラベルの横に小さな情報アイコンが表示されると、問題は正常にわかります。このアイコンをクリックすると、プロビジョニング プロファイルの詳細が表示されます。

iOS アプリの接続

アプリの接続について詳しくは、Firebase を iOS プロジェクトに追加する方法のドキュメントをご覧ください。まず、Firebase コンソールで次の主な手順を行います。

  1. 新しいプロジェクトの [プロジェクトの概要] 画面で [+ アプリを追加] ボタンをクリックし、[iOS+] アイコンをクリックして新しい iOS アプリを Firebase プロジェクトに追加します。
  2. アプリのバンドル ID を入力します(com.acme.samples.firebase.quickstart.DatabaseExample など、前のセクションで定義した ID を使用します。これは一意の識別子である必要があります
  3. [アプリを登録] をクリックします。
  4. Firebase は、アプリに必要なすべての Firebase メタデータを含む GoogleService-Info.plist ファイルを生成します。
  5. [Download GoogleService-Info.plist] をクリックしてファイルをダウンロードします。
  6. Xcode では、プロジェクトにすでに GoogleService-Info.plist という名前のファイルが含まれていることがわかります。まずこのファイルを削除してください。次のステップで、このファイルはご自身の Firebase プロジェクト用に置き換えます。
  7. 前の手順でダウンロードした GoogleService-Info.plist ファイルを Xcode プロジェクトのルートフォルダにコピーし、DatabaseExample (iOS) ターゲットに追加します。名前が GoogleService-Info.plist になっていることを確認します。
  8. 登録フローの残りの手順をクリックします。サンプル プロジェクトはすでに正しく設定されているため、コードを変更する必要はありません。

Firebase Authentication を構成する

ぜひここまででかなり多くの設定を行うことになりますが、少々お待ちください。Firebase を初めて使用する場合は、ワークフローの重要な部分を目にしたはずです。これらはすぐに理解できるでしょう。

次に、このアプリの Firebase Authentication を構成します。

認証メール/パスワード ログイン プロバイダを有効にする

  1. 引き続き Firebase コンソールで、コンソールの [Authentication] セクションを開きます。
  2. [使ってみる] をクリックして、プロジェクトに Firebase Authentication を設定します。
  3. [ログイン方法] タブを選択します。
  4. [ネイティブ プロバイダ] セクションで [メール/パスワード] を選択します。
  5. [メール/パスワード] を有効にして [保存] をクリックします。

テストユーザーを追加する

  1. [Authentication] セクションの [Users] タブを開きます。
  2. [ユーザーを追加] をクリックします。
  3. テストユーザーのメールアドレスとパスワードを指定して、[ユーザーを追加] をクリックします。

アプリを試してみましょう

Xcode に戻り、iOS Simulator でアプリケーションを実行します。作成したテストユーザーのメールアドレスとパスワードを使用してログインします。ログインしたら、投稿を作成したり、既存の投稿にコメントを投稿したり、投稿にスターを付けたり外したりできます。

6. App Attest 証明書プロバイダを構成する

このステップでは、Firebase コンソールで App Attest プロバイダを使用するように App Check を構成します。

  1. Firebase コンソールで、コンソールの [App Check] セクションに移動します。
  2. [Get started] をクリックします。
  3. [アプリ] タブで、アプリをクリックして詳細を開きます。
  4. [App Attest] をクリックして App Attest を構成し、Apple Developer アカウントのチーム ID を入力します(これは、Apple Developer ポータルの [Membership] セクションで確認できます)。1645f7a369b678c2.png
  5. [保存] をクリックします。

これで、稼働中の Firebase プロジェクトが新しいアプリに接続され、App Check が有効になっています。

これで、特定の構成証明サービスを構成する準備が整いました。このワークフローの詳細については、iOS で App Attest を使用して App Check を有効にするをご覧ください。

7. アプリケーションに App Attest を構成する

それでは、Firebase App Check SDK を使ってクライアント コードを実装しましょう。

まず、SDK が Apple の App Attest API を使用して、アプリから送信されたリクエストがアプリの正規インスタンスから送信されるように、Xcode プロジェクトを構成する必要があります。

  1. Xcode プロジェクトにアプリ ターゲットの App Attest 機能を追加します。
  2. アプリのターゲット設定で [Signing & Capabilities] タブを開く
  3. [+] ボタンをクリックします。
  4. ダイアログで、[App Attest] ケーパビリティ ae84cd988a5fab31.png を探して選択します。
  5. 前のステップを実行すると、Xcode プロジェクトのルートフォルダにファイル DatabaseExample (iOS).entitlements が表示されます。
  6. DatabaseExample (iOS).entitlements ファイルで、App Attest Environment キーの値を production. に変更します。

以上の手順を完了し、実機の iOS デバイス(iPhone、iPad)でアプリを起動しても、アプリは引き続き Realtime Database にアクセスできます。後のステップで App Check を適用し、不正なアプリやデバイスからのリクエストの送信をブロックします。

このワークフローの詳細については、iOS で App Attest を使用して App Check を有効にするをご覧ください。

8. iOS シミュレータ用のデバッグ認証プロバイダを構成する

Firebase App Check Debug プロバイダを使用すると、開発プロセス中に、信頼できない環境(iOS シミュレータなど)で Firebase App Check を適用したアプリケーションをテストできます。次に、デバッグ プロバイダをまとめて構成する必要があります。

アプリに Firebase デバッグ プロバイダをインストールする

オプション 1: ファクトリでデバッグ プロバイダのインスタンスを条件付きで作成する

この操作のほとんどは、App Check プロバイダ ファクトリを作成したときに行いました。このステップでは、デバッグ プロバイダによって生成されたローカル デバッグ シークレットのログを追加します。これにより、デバッグのためにアプリのこのインスタンスを Firebase コンソールに登録できます。

MyAppCheckProviderFactory.swift を次のコードで更新します。

import Firebase

class MyAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
  func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
#if targetEnvironment(simulator)
    // App Attest is not available on simulators.
    // Use a debug provider.
    let provider = AppCheckDebugProvider(app: app)

    // Print only locally generated token to avoid a valid token leak on CI.
    print("Firebase App Check debug token: \(provider?.localDebugToken() ?? "" )")

    return provider
#else
    // Use App Attest provider on real devices.
    return AppAttestProvider(app: app)
#endif
  }
}

このアプローチにより、環境に応じて App Check をより柔軟に構成できるようになりました。たとえば、App Attest を利用できない OS バージョンでは、DeviceCheck やカスタム証明書プロバイダなどの他の証明書プロバイダを使用できます。以下の例をご覧ください。

import Firebase

class MyAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
  func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
      #if targetEnvironment(simulator)
      // App Attest is not available on simulators.
      // Use a debug provider.
      let provider = AppCheckDebugProvider(app: app)

      // Print only locally generated token to avoid a valid token leak on CI.
      print("Firebase App Check debug token: \(provider?.localDebugToken() ?? "" )")

      return provider
      #else
      if #available(iOS 14.0, *) {
        // Use App Attest provider on real devices.
        return AppAttestProvider(app: app)
      } else {
        return DeviceCheckProvider(app: app)
      }
      #endif
  }
}

オプション 2: AppCheckDebugProviderFactory をインストールする

より簡単なケースでは、Firebase アプリケーション インスタンスを構成する前に、AppCheckDebugProviderFactory を一時的または条件付きでインストールできます。

init() {
#if targetEnvironment(simulator)
  let providerFactory = AppCheckDebugProviderFactory()
#else
  let providerFactory = MyAppCheckProviderFactory()
#endif

  AppCheck.setAppCheckProviderFactory(providerFactory)

  FirebaseApp.configure()
}

これにより、独自の App Check プロバイダ ファクトリを作成するための数行のコードを削減できます。

Firebase コンソールでデバッグ シークレットを登録する

iOS Simulator からデバッグ シークレットを取得する

  1. AppCheckDebugProviderFactory(上記のオプション 2)をインストールする場合は、アプリの起動引数に -FIRDebugEnabled を追加して、アプリのデバッグ ロギングを有効にする必要があります。f1c6b477a373e144.png
  2. シミュレータでアプリを実行する
  3. Xcode コンソールでデバッグ シークレットを確認します。コンソール フィルタを使用すると、すばやく見つけることができます: d4c65af93e369c55.png

注: デバッグ シークレットは、アプリの初回起動時にシミュレータ用に生成され、ユーザーのデフォルトに保存されます。アプリを削除したり、シミュレータをリセットしたり、別のシミュレータを使用したりすると、新しいデバッグ シークレットが生成されます。必ず新しいデバッグ シークレットを登録してください。

デバッグ シークレットを登録する

  1. Firevbase コンソールに戻り、[App Check] セクションに移動します。
  2. [アプリ] タブで、アプリをクリックして詳細を開きます。
  3. オーバーフロー メニューで [デバッグ トークンを管理] を選択します。d77c8ff768a00b4b.png
  4. Xcode コンソールからコピーしたシークレットを追加して、[保存 ] f845c97b86f694d0.png をクリックします。

この手順を行うと、App Check を適用した状態でも、Simulator でアプリを使用できるようになります。

注: デバッグ プロバイダは、デバッグ シークレットの漏洩を防ぐために特別に設計されています。現在のアプローチでは、デバッグ シークレットをソースコードに保存する必要はありません。

このフローについて詳しくは、ドキュメントで iOS のデバッグ プロバイダで App Check を使用するをご覧ください。

9. Firebase Realtime Database で App Check の適用を有効にする

現時点では、実際のデバイスの AppAttestProvider を返す AppCheckProviderFactory を宣言します。実機で実行する場合、アプリは構成証明を実行し、結果を Firebase バックエンドに送信します。ただし、Firebase バックエンドは引き続き、あらゆるデバイス、iOS シミュレータ、スクリプトなどからのリクエストを受け入れます。このモードは、App Check を使用していない古いバージョンのアプリを使用しているユーザーがいて、まだアクセス チェックを適用したくない場合に便利です。

次に、App Check の適用を有効にして、正規のデバイスからのみ Firebase アプリにアクセスできるようにする必要があります。Firebase プロジェクトで適用を有効にすると、App Check と統合されていない古いバージョンのアプリは機能しなくなります。

  1. Firebase コンソールの [App Check] セクションで、[Realtime Database] をクリックして詳細を展開します。
  2. [適用] をクリックします。

64e6a81fa979b635.png

  1. 確認ダイアログの情報を確認し、[適用] をクリックします。

これらの手順を完了すると、正規のアプリのみがデータベースにアクセスできるようになります。その他のアプリはすべてブロックされます。

不正なアプリから Realtime Database にアクセスしてみる

App Check の適用を実際に確認する手順は次のとおりです。

  1. DatabaseExampleApp のアプリ エントリ ポイントの init メソッドで、App Check 登録コードをコメントアウトして、App Check の登録を無効にします。
  2. [デバイス] > [すべてのコンテンツと設定を消去] の順に選択して、シミュレータをリセットします。この操作を行うとシミュレータがワイプされ、デバイス トークンが無効になります。
  3. シミュレータでアプリを再度実行します。
  4. 次のエラー メッセージが表示されます。
    [FirebaseDatabase][I-RDB034005] Firebase Database connection was forcefully killed by the server.  Will not attempt reconnect. Reason: Invalid appcheck token.
    

App Check を再度有効にするには:

  1. DatabaseExampleApp で App Check 登録コードのコメント化を解除します。
  2. アプリを再起動します。
  3. Xcode のコンソールで新しい App Check トークンをメモします。
  4. Firebase コンソールで、アプリの App Check 設定でデバッグ トークンを登録します。
  5. アプリを再実行します。
  6. エラー メッセージは表示されなくなり、アプリで新しい投稿やコメントを追加できるようになります。

10. お疲れさまでした

9785d32f18b995d2.gif

ここでは、以下の方法について学びました。

  • 既存のプロジェクトに App Check を追加する
  • アプリの本番環境バージョンに App Attest 証明書プロバイダを構成する
  • シミュレータでアプリをテストするデバッグ証明書プロバイダを構成する
  • アプリのバージョン ロールアウトを観察し、Firebase プロジェクトに App Check を適用するタイミングを確認する
  • App Check の適用を有効にする

次のステップ

Firebase Remote Config を使用して Firebase App Check を段階的にロールアウトする Codelab で、Remote Config を使用して App Check を段階的にユーザーにロールアウトする方法を学びます。

役に立つその他のリソース

ほとんどの場合は、この Codelab で説明する設定で機能しますが、App Check の方が必要に応じて柔軟に使用できます。詳細については、次のリンクをご覧ください。