📱
HTTPv1による認証でiOSアプリのプッシュ通知をFirebaseで実装した話
はじめに
Firebase Cloud Messaging(FCM)を利用して、iOSアプリでプッシュ通知を実装する際に、HTTPv1 APIを使った認証を導入した。その理由や実装手順について説明する。
なぜHTTPv1 APIを選んだのか?
以前のFCM通知APIでは、**Firebaseプロジェクトのサーバーキーを使った認証(Legacy HTTP API)**が提供されていた。しかし、Googleは2024年にこの方式を廃止し、HTTPv1 APIへの移行を推奨している。
HTTPv1 APIのメリット
- IAM(Identity and Access Management)を活用した認証管理ができる。
- セキュリティが強化され、プロジェクト単位ではなく、より細かいアクセス制御が可能。
- **より詳細な通知設定(データペイロードの拡張)**ができる。
そのため、今回の実装ではHTTPv1 APIを利用した。
ディレクトリ構造と関係ファイル
プッシュ通知に関連するコードは、以下のようなディレクトリ構造で管理した。
📂 SharedShoppingList
├── 📂 Firebase
│ ├── NotificationManager.swift // 通知の設定と送信を担当
│ ├── SessionManager.swift // ユーザーのFCMトークンを管理
│ ├── AppDelegate.swift // Firebaseの初期化とAPNs登録
├── 📂 CloudFunctions
│ ├── index.js // Firebase Cloud Functionsで通知を送信
├── 📂 Views
│ ├── SettingsView.swift // 通知設定のUI
Firebase Cloud Messagingの設定手順
1. Firebaseプロジェクトの作成
- Firebase Console にアクセスし、新規プロジェクトを作成する。
-
Cloud Messaging を有効化する。
- 「プロジェクト設定」>「Cloud Messaging」に移動し、「APNs認証キー」を追加。
2. 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
に記述する。
3. FirestoreにFCMトークンを保存
ユーザーごとにデバイスのFCMトークンをFirestoreに保存する。
SessionManager.swift
import FirebaseAuth
import FirebaseFirestore
import FirebaseMessaging
class SessionManager: ObservableObject {
@Published var isLoggedIn: Bool = false
init() {
Auth.auth().addStateDidChangeListener { [weak self] _, user in
if let user = user {
self?.updateFCMToken() // 🔥 FCMトークンを保存
}
}
}
func updateFCMToken() {
Messaging.messaging().token { token, error in
if let token = token {
let db = Firestore.firestore()
let deviceId = UIDevice.current.identifierForVendor?.uuidString ?? "デバイスID"
db.collection("devices").document(deviceId).setData([
"fcmTokens": [token],
"userId": Auth.auth().currentUser?.uid ?? "ユーザーID",
"lastUpdated": Timestamp(date: Date())
], merge: true)
}
}
}
}
このコードを SessionManager.swift
に記述する。
HTTPv1 APIを使った通知送信
4. Google Cloudの設定(IAMと認証)
- Firebase Consoleの「プロジェクト設定」→「サービスアカウント」を開く。
- 「新しい秘密鍵を生成」を選択し、JSONファイルをダウンロード。
- Google Cloud IAMで、「Firebase Cloud Messaging API」を有効化する。
5. Firebase Cloud Functionsの実装
通知を送るために、Firebase 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
に記述する。
6. iOSアプリから通知を送信
アプリからCloud Functionsのエンドポイントを呼び出して、通知を送る。
NotificationManager.swift
import FirebaseFirestore
class NotificationManager {
static let shared = NotificationManager()
func sendNotification(to token: String, title: String, body: String) {
let url = URL(string: "<https://クラウドファンクションURL>")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let payload: [String: Any] = [
"token": token,
"title": title,
"body": body
]
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
URLSession.shared.dataTask(with: request) { data, _, error in
if let error = error {
print("通知送信エラー: \\(error.localizedDescription)")
}
}.resume()
}
}
このコードを Firebase/NotificationManager.swift
に記述する。
まとめ
- FirebaseのLegacy HTTP APIが2024年に廃止されるため、HTTPv1 APIを採用した。
- APNsの設定とFCMトークンの管理を実装した。
- Firebase Cloud Functionsを用いてサーバー側で通知を送信する仕組みを構築した。
- iOSアプリからCloud Functionsを呼び出して、通知を送るようにした。
この実装により、複数人でリアルタイムで買い物リストの変更を通知できるシステムが構築できた。
Discussion