Skip to content

feat: add setFirebaseOptions() for runtime multi-tenant Firebase configuration#192

Open
Aravinthan-J wants to merge 3 commits into
capacitor-community:masterfrom
Aravinthan-J:feat/set-firebase-options
Open

feat: add setFirebaseOptions() for runtime multi-tenant Firebase configuration#192
Aravinthan-J wants to merge 3 commits into
capacitor-community:masterfrom
Aravinthan-J:feat/set-firebase-options

Conversation

@Aravinthan-J

@Aravinthan-J Aravinthan-J commented May 26, 2026

Copy link
Copy Markdown

Summary

Adds a setFirebaseOptions() method that allows apps to initialize Firebase with credentials provided at runtime, rather than relying solely on static google-services.json / GoogleService-Info.plist files baked into the binary.

This unblocks multi-tenant SaaS apps where each tenant operates their own Firebase project and the correct credentials are only known after the user authenticates.

Closes #60


Motivation

In multi-tenant apps, push notification tokens must be scoped to the correct Firebase project per tenant. There is currently no way to do this with this plugin — the only path was to either:

  • Ship a separate binary per tenant (impractical for SaaS)
  • Maintain a fork of this plugin

This PR upstreams the implementation from an internal fork that has been running in production on Capacitor 5/6/7.


Changes

src/definitions.ts

  • Adds FirebaseOptions interface
  • Adds setFirebaseOptions(options: FirebaseOptions): Promise<void> to FCMPlugin

src/web.ts

  • Adds setFirebaseOptions() stub (throws unimplemented — native-only)

Android (FCMPlugin.java)

Creates a named secondary FirebaseApp ("FCM") so it does not conflict with or re-initialize any default app already present from google-services.json. All getToken() / refreshToken() / setAutoInit() / isAutoInitEnabled() calls are automatically routed through the secondary app when set.

Note: gcmSenderId is accepted for interface parity with iOS but omitted from FirebaseOptions.BuildersetGcmSenderId() was removed in Firebase Android SDK 29+.

iOS (FCMPlugin.swift)

  • load() now checks for the presence of GoogleService-Info.plist before calling FirebaseApp.configure(), so apps without a plist don't crash on startup
  • setFirebaseOptions() configures the default Firebase app with runtime credentials; fails fast with a clear error if Firebase is already initialized (Firebase SDK limitation — re-initialization is not supported on iOS)

Usage

import { FCM } from '@capacitor-community/fcm';
import { PushNotifications } from '@capacitor/push-notifications';

// After login — fetch tenant config from your server
const config = await fetchTenantFirebaseConfig();

await FCM.setFirebaseOptions({
  applicationId: config.mobilesdk_app_id, // Android: mobilesdk_app_id / iOS: GOOGLE_APP_ID
  gcmSenderId:   config.project_number,
  apiKey:        config.apiKey,
  projectId:     config.project_id,
});

await PushNotifications.register();
const { token } = await FCM.getToken();
// token is now scoped to the tenant's Firebase project

Platform behaviour summary

Android iOS
Mechanism Named secondary FirebaseApp("FCM") Configures default app at runtime
Coexists with static config file Yes — secondary app is independent No — do not ship GoogleService-Info.plist
Re-initialization (tenant switch) Yes — reuses existing secondary app No — app restart required (Firebase SDK limitation)

Known limitations / follow-up

  • iOS re-initialization: Once FirebaseApp.configure() is called it cannot be undone. Apps that need to switch tenants at runtime on iOS must restart.
  • iOS secondary app for Messaging: The Firebase iOS SDK does not expose a public Messaging(app:) API, so getToken() on iOS always uses the default app (which is configured by setFirebaseOptions()).

Testing

Tested on:

  • Android (Capacitor 7, Firebase Android SDK 33)
  • iOS (Capacitor 7, Firebase iOS SDK 11)

Existing behaviour is fully preserved when setFirebaseOptions() is never called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multiple SenderIDs/FCM projects?

1 participant