I'm building a Flutter app that uses Firebase Auth and Firestore. Everything works fine on the Flutter side.
Now, I need to save battery info from iOS native Swift code (in AppDelegate.swift
) so it can run in the background — which Flutter doesn't support directly.
To do this, I'm using a secondary FirebaseApp instance in Swift (named "flutter-app"
), and I'm trying to write to Firestore using the existing user who was already authenticated in Flutter.
However, when I try to write to Firestore from Swift, I get this error:
[FirebaseFirestore][I-FST000001] WriteStream (313536646433373138) Stream error: 'Permission denied: Missing or insufficient permissions.'
[FirebaseFirestore][I-FST000001] Write at users/{uid}/devices/{deviceId} failed: Missing or insufficient permissions.
Even though:
auth.currentUser
in Swift is not nil
The uid
matches the one from the Flutter side
Firestore rules are correctly configured to allow users to write to their own documents
The same code path (writing to users/{uid}/devices/{deviceId}
) works fine in Flutter
I initialized the secondary FirebaseApp
using the same GoogleService-Info.plist
as in Flutter.
I verified that FirebaseApp
only initializes once and reuses the instance afterward.
I used Auth.auth(app: app)
and checked that currentUser
is valid.
I expected the write to Firestore to succeed, just like in Flutter, since the user is already logged in and Firestore rules allow it.
Here’s the relevant Swift code:
if FirebaseApp.app(name: "flutter-app") == nil {
let path = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist")!
let options = FirebaseOptions(contentsOfFile: path)!
FirebaseApp.configure(name: "flutter-app", options: options)
}
let app = FirebaseApp.app(name: "flutter-app")!
let db = Firestore.firestore(app: app)
let auth = Auth.auth(app: app)
guard let currentUser = auth.currentUser else {
print("User not logged in")
return
}
// ... build docRef and call setData() ...
Here are the Firestore rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write, update: if request.auth != null && request.auth.uid == userId;
match /devices/{deviceId} {
allow read, write, update: if request.auth != null && request.auth.uid == userId;
}
}
}
}
If there's anything I'm missing about how authentication works across native/Flutter with secondary FirebaseApp
, I’d really appreciate any help or suggestions!
The issue was caused by Firebase dose not use the same instance in both flutter and swift, and Firestore being accessed from Swift before Flutter had finished initializing it.
Since Firestore locks its settings at first access, calling Firestore.firestore() too early in Swift (before Flutter finishes initialization) caused a fatal crash.
To fix it, I made sure Flutter fully initialized Firebase and triggered a dummy Firestore call before any Swift code touched Firestore. In main.dart, I added:
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await FirebaseFirestore.instance.collection("initcheck").limit(1).get();
Since my Firestore rules required authentication, I also added:
match /initcheck/{docId} {
allow read: if request.auth != null;
}
After that, saving data from Swift using the logged-in user worked perfectly.