Issue
When using @react-native-firebase/storage with a Firebase app that was initialized dynamically via initializeApp(options, appName) in JavaScript (rather than using the [DEFAULT] app from a natively-bundled google-services.json / GoogleService-Info.plist), calls to getDownloadURL() fail with [storage/unauthorized] because the native module does not attach the Authorization header to the outgoing HTTP request.
Reproduction
- Initialize a named Firebase app dynamically:
const app = await initializeApp({
appId: "...",
projectId: "my-project",
apiKey: "...",
storageBucket: "my-project.appspot.com",
// ...
}, "my-named-app");
- Sign in with a custom token on that named app:
await signInWithCustomToken(getAuth(app), customToken);
-
Confirm auth works — getAuth(app).currentUser is non-null with correct claims including the custom claims required by storage security rules.
-
Attempt to get a download URL:
// All of these fail with [storage/unauthorized]:
// Namespace API:
await storage(app).refFromURL("gs://my-project.appspot.com/some/file.png").getDownloadURL();
// Method on app:
await (app as any).storage().refFromURL("gs://my-project.appspot.com/some/file.png").getDownloadURL();
// Modular API:
await getDownloadURL(refFromURL(storage(app), "gs://my-project.appspot.com/some/file.png"));
// Default app (which has no signed-in user):
await storage().refFromURL("gs://my-project.appspot.com/some/file.png").getDownloadURL();
- The same request succeeds when made manually via
fetch with an explicit Authorization: Bearer header using the token from getAuth(app).currentUser.getIdToken():
const token = await getAuth(app).currentUser.getIdToken();
const encodedPath = encodeURIComponent("some/file.png");
const url = `https://firebasestorage.googleapis.com/v0/b/my-project.appspot.com/o/${encodedPath}?alt=media`;
const response = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
});
// response.status === 200
Diagnosis
Using Proxyman to inspect network traffic from the iOS simulator, we confirmed:
- The manual
fetch call includes the Authorization: Bearer <token> header and succeeds (200)
- The native storage SDK request does not include the
Authorization header and fails (403)
The [DEFAULT] Firebase app (created from the natively-bundled google-services.json) points to the same Firebase project but has no signed-in user. The storage module appears to either not resolve the auth token for named apps, or falls back to the [DEFAULT] app's (empty) auth state when constructing the native request.
Additional context
- The natively-bundled
google-services.json / GoogleService-Info.plist points to the same Firebase project — the [DEFAULT] app exists but has no signed-in user
- The named app is created at runtime during a device pairing flow, which is why we cannot use the
[DEFAULT] app
refFromURL() succeeds and correctly resolves the bucket and full path — only getDownloadURL() fails
- Tested on iOS simulator
Workaround
Bypass the storage SDK entirely and use the Firebase Storage REST API with an explicit bearer token:
const token = await getAuth(app).currentUser.getIdToken();
const encodedPath = encodeURIComponent(storagePath);
const url = `https://firebasestorage.googleapis.com/v0/b/${bucket}/o/${encodedPath}?alt=media`;
const response = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
});
Project Files
Javascript
Click To Expand
package.json:
{
"@react-native-firebase/app": "^23.7.0",
"@react-native-firebase/auth": "^23.7.0",
"@react-native-firebase/firestore": "^23.7.0",
"@react-native-firebase/messaging": "^23.7.0",
"@react-native-firebase/storage": "^23.7.0"
}
firebase.json for react-native-firebase v6:
iOS
Click To Expand
ios/Podfile:
# Managed by Expo — standard Expo SDK 53 Podfile
AppDelegate.m:
Android
Click To Expand
Have you converted to AndroidX?
android/build.gradle:
android/app/build.gradle:
android/settings.gradle:
MainApplication.java:
AndroidManifest.xml:
Environment
Click To Expand
react-native info output:
React Native (Expo SDK 53, New Architecture enabled)
iOS Simulator
- Platform that you're experiencing the issue on:
react-native-firebase version you're using that has this issue:
@react-native-firebase/storage@23.7.0
Firebase module(s) you're using that has the issue:
- Are you using
TypeScript?
Issue
When using
@react-native-firebase/storagewith a Firebase app that was initialized dynamically viainitializeApp(options, appName)in JavaScript (rather than using the[DEFAULT]app from a natively-bundledgoogle-services.json/GoogleService-Info.plist), calls togetDownloadURL()fail with[storage/unauthorized]because the native module does not attach theAuthorizationheader to the outgoing HTTP request.Reproduction
Confirm auth works —
getAuth(app).currentUseris non-null with correct claims including the custom claims required by storage security rules.Attempt to get a download URL:
fetchwith an explicitAuthorization: Bearerheader using the token fromgetAuth(app).currentUser.getIdToken():Diagnosis
Using Proxyman to inspect network traffic from the iOS simulator, we confirmed:
fetchcall includes theAuthorization: Bearer <token>header and succeeds (200)Authorizationheader and fails (403)The
[DEFAULT]Firebase app (created from the natively-bundledgoogle-services.json) points to the same Firebase project but has no signed-in user. The storage module appears to either not resolve the auth token for named apps, or falls back to the[DEFAULT]app's (empty) auth state when constructing the native request.Additional context
google-services.json/GoogleService-Info.plistpoints to the same Firebase project — the[DEFAULT]app exists but has no signed-in user[DEFAULT]apprefFromURL()succeeds and correctly resolves the bucket and full path — onlygetDownloadURL()failsWorkaround
Bypass the storage SDK entirely and use the Firebase Storage REST API with an explicit bearer token:
Project Files
Javascript
Click To Expand
package.json:{ "@react-native-firebase/app": "^23.7.0", "@react-native-firebase/auth": "^23.7.0", "@react-native-firebase/firestore": "^23.7.0", "@react-native-firebase/messaging": "^23.7.0", "@react-native-firebase/storage": "^23.7.0" }firebase.jsonfor react-native-firebase v6:# N/AiOS
Click To Expand
ios/Podfile:# Managed by Expo — standard Expo SDK 53 PodfileAppDelegate.m:// Managed by ExpoAndroid
Click To Expand
Have you converted to AndroidX?
android/gradle.settingsjetifier=truefor Android compatibility?jetifierfor react-native compatibility?android/build.gradle:// Managed by Expoandroid/app/build.gradle:// Managed by Expoandroid/settings.gradle:// Managed by ExpoMainApplication.java:// Managed by ExpoAndroidManifest.xml:<!-- Managed by Expo -->Environment
Click To Expand
react-native infooutput:react-native-firebaseversion you're using that has this issue:@react-native-firebase/storage@23.7.0Firebasemodule(s) you're using that has the issue:StorageTypeScript?Yes, TypeScript 5.x