0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HTTPv1による認証とFirebaseでiOSアプリのプッシュ通知を実装した話

Posted at

HTTPv1による認証とFirebaseでiOSアプリのプッシュ通知を実装した話

はじめに

iOSアプリでFirebase Cloud Messaging(FCM)を利用したプッシュ通知を実装する際に、HTTPv1 APIを使った認証Firebase Cloud Functionsを導入した。本記事では、なぜこの2つを採用したのか、具体的な設定方法と実装のポイントを説明する。

HTTPv1 APIとCloud Functionsの採用理由

HTTPv1 APIとは?

Firebase Cloud Messaging(FCM)では、クライアントアプリ(iOSやAndroid)にプッシュ通知を送信するためのAPIが提供されている。このAPIには、かつてレガシーAPI(Legacy HTTP API)が使用されていたが、2024年7月22日をもって廃止され、現在はHTTPv1 APIが唯一の正式な方法となっている【公式ドキュメント参照】(Firebase公式ドキュメント)。

HTTPv1 APIの特長

  • IAMによる認証管理
    • Google Cloud IAM(Identity and Access Management)を活用し、より細かいアクセス制御が可能。
  • 通知の柔軟なカスタマイズ
    • JSONペイロードの構造が拡張され、通知の内容や送信方法を細かく設定できる。
  • 複数の受信者への一括送信
    • トピックベースやデバイスグループを利用し、一括通知が可能。

Firebase Cloud Functionsとは?

Firebase Cloud Functionsは、Google Cloudのサーバーレス環境で実行されるコードをホスティングするサービスである。
Firebase上でイベントが発生した際に、そのイベントに応じた処理を自動的に実行することができる。

Cloud Functionsの特長

  • サーバー管理不要のサーバーレス環境
    • 自前でサーバーを用意せずに、イベントに応じた処理を記述・実行できる。
  • Firestoreや認証との連携が容易
    • Firestoreのデータ変更、ユーザーの認証状態変更などをトリガーにして、処理を自動化できる。
  • HTTPリクエストのエンドポイントを提供できる
    • iOSアプリなどのクライアントが直接呼び出せるAPIを作成可能で、セキュアな通知送信を実装できる。

公式ドキュメントはこちら:
Firebase Cloud Functions

なぜCloud Functionsを採用したのか?

HTTPv1 APIを利用するには、クライアントアプリ(iOS)から直接Firebaseにリクエストを送るのではなく、サーバー経由で認証を行うのが推奨されている。そのため、Firebase Cloud Functionsを活用し、バックエンドで通知を処理する方式を採用した。

Cloud Functionsを利用するメリット

  1. FCMの認証情報をクライアントアプリに持たせずに済む
    • クライアントアプリから直接HTTPv1 APIを呼び出すと、Googleの認証トークンをアプリ内で管理する必要がある。しかし、これはセキュリティリスクとなる。
    • Cloud Functionsを経由することで、サーバーサイドで認証情報を管理できる
  2. スケーラブルな通知処理が可能
    • 複数のユーザーへの一括通知、特定のグループへの通知送信を簡単に処理できる。
  3. Firestoreと連携しやすい
    • Firestoreに保存されているユーザーのデバイス情報やトークンを基に、自動で通知を送信できる。

ディレクトリ構造と関係ファイル

プッシュ通知に関連するコードは、以下のようなディレクトリ構造で管理した。

📂 SharedShoppingList
 ├── 📂 Firebase
 │    ├── NotificationManager.swift  // 通知の設定と送信を担当
 │    ├── SessionManager.swift       // ユーザーのFCMトークンを管理
 │    ├── AppDelegate.swift          // Firebaseの初期化とAPNs登録
 ├── 📂 CloudFunctions
 │    ├── index.js                   // Firebase Cloud Functionsで通知を送信
 ├── 📂 Views
 │    ├── SettingsView.swift         // 通知設定のUI

Firebase Cloud Messagingの設定手順

Firebaseプロジェクトの作成とCloud Messagingの設定

  1. Firebase Console にアクセスし、新規プロジェクトを作成する。
  2. Cloud Messaging を有効化する。
    • 「プロジェクト設定」>「Cloud Messaging」に移動し、「APNs認証キー」を追加。

APNsの設定とFCMの連携

iOSアプリでプッシュ通知を受信するために、**Apple Push Notification Service(APNs)**とFirebaseを統合する。

AppDelegate.swift

import Firebase
import FirebaseMessaging
import UserNotifications

class AppDelegate: NSObject, UIApplicationDelegate, MessagingDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        FirebaseApp.configure()
        NotificationManager.shared.configure() // 🔥 通知設定
        Messaging.messaging().delegate = self
        return true
    }

    // 🔥 APNsトークンの取得
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().apnsToken = deviceToken
    }
}

このコードを AppDelegate.swift に記述する

Firebase Cloud Functionsで通知を送信する

Google Cloudの設定(IAMと認証)

  1. Firebase Consoleの「プロジェクト設定」→「サービスアカウント」を開く。
  2. 「新しい秘密鍵を生成」を選択し、JSONファイルをダウンロード。
  3. Google Cloud IAMで、「Firebase Cloud Messaging API」を有効化する。

Cloud Functionsの実装

index.js

const functions = require("firebase-functions");
const admin = require("firebase-admin");
const { google } = require("googleapis");

admin.initializeApp();

const PROJECT_ID = "プロジェクトID";
const SCOPES = ["https://www.googleapis.com/auth/firebase.messaging"];

async function getAccessToken() {
  const auth = new google.auth.GoogleAuth({ scopes: SCOPES });
  const client = await auth.getClient();
  const tokens = await client.getAccessToken();
  return tokens.token;
}

exports.sendPushNotification = functions.https.onRequest(async (req, res) => {
  const { token, title, body } = req.body;
  if (!token || !title || !body) return res.status(400).send("Missing fields");

  try {
    const accessToken = await getAccessToken();
    const message = {
      message: {
        token: token,
        notification: { title, body },
      },
    };

    const response = await fetch(`https://fcm.googleapis.com/v1/projects/${PROJECT_ID}/messages:send`, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${accessToken}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(message),
    });

    res.status(200).send(await response.json());
  } catch (error) {
    res.status(500).send("Error sending notification");
  }
});

このコードを CloudFunctions/index.js に記述する

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?