Description
🔥 Issue
Describe your issue here
HTTPS Callable Cloud Functions (onCall
, v2 syntax) invoked from a React Native app using @react-native-firebase/functions
's httpsCallable
method consistently fail with an "unauthenticated"
error (Cloud Function logs show request.auth
is missing/null). This failure occurs even though the client app explicitly confirms that auth.currentUser
is valid and authenticated immediately before making the call.
This issue persists across environments:
- When targeting local Firebase Emulators: The call reaches the function emulator, but
request.auth
is null. - When targeting the live deployed function: The exact same
"unauthenticated"
error is returned to the client.
Further Context & Troubleshooting:
- Client Auth Confirmed:
console.log(auth.currentUser.uid)
before thehttpsCallable
confirms a valid, logged-in user. Forcing token refresh withgetIdToken(true)
also succeeds. - Basic Connectivity Works: A separate non-authenticated
onCall
function (testNoAuth
) invoked viahttpsCallable
from the same client code succeeds when targeting the emulator. This proves basic function invocation works. onRequest
Workaround Failure (Emulator): Attempting anonRequest
function with manual token verification (admin.auth().verifyIdToken
) usingfetch
from the client failed in the emulator. The Functions emulator log showedadmin.initializeApp()
failed to detect theFIREBASE_AUTH_EMULATOR_HOST
environment variable, causingverifyIdToken
to fail ("Invalid signature"). This secondary issue might hint at broader problems with SDK/emulator environment interaction.- Hypothesis: The
@react-native-firebase/functions
module (v21.14.0) appears to be failing to automatically attach the necessary authentication context/token from the@react-native-firebase/auth
module (v21.14.0) when makinghttpsCallable
requests.
Relevant Client Code Snippet (App.js
):
// Import statements (simplified)
import { getApp } from "@react-native-firebase/app";
import '@react-native-firebase/functions'; // Ensure module is loaded
import { auth } from "./firebase/firebaseConfig"; // Firebase Web SDK auth instance
// Function making the call
export async function sendDopamineUpdateToServer(timeData) {
console.log(`[sendDopamineUpdateToServer ENTRY] Auth State:`, auth.currentUser ? `User ${auth.currentUser.uid}` : 'NULL'); // Confirms auth
const user = auth.currentUser;
if (!user) {
console.error("[sendDopamineUpdateToServer] Skipping: User not authenticated.");
return { success: false, error: 'User not authenticated', skipped: true };
}
// ... payload setup ...
console.log(`[sendDopamineUpdateToServer] User ${user.uid} authenticated. Proceeding with httpsCallable...`);
try {
// Optional: await auth.currentUser.getIdToken(true); // Tried this, also succeeds
const payload = { /* ... */ };
console.log(`[sendDopamineUpdateToServer] Calling 'updateDopamineState' with payload:`, payload);
// Using getApp() as per v6+ recommendations
const updateFunction = getApp().functions('us-central1').httpsCallable('updateDopamineState');
const functionResult = await updateFunction(payload);
console.log("[sendDopamineUpdateToServer] Backend 'updateDopamineState' (onCall) result:", functionResult.data);
// ... success handling ...
} catch (error) {
console.error("[sendDopamineUpdateToServer] Error calling 'updateDopamineState' (onCall):", error);
// Logs show: code: 'unauthenticated', message: 'The function must be called while authenticated.'
if (error.code) console.error("Function Error Code:", error.code);
if (error.message) console.error("Function Error Message:", error.message);
// ... failure handling ...
}
}
// Emulator setup (currently commented out for live testing, but issue persists both ways)
/*
import rnAuth from '@react-native-firebase/auth'; // Import for emulator setup
useEffect(() => {
if (__DEV__) {
console.log("🔧 DEVELOPMENT MODE: Connecting to Firebase Emulators...");
try {
const host = Platform.OS === 'android' ? '10.0.2.2' : 'localhost';
rnAuth().useEmulator(`http://${host}:9099`); // Using @react-native-firebase/auth for emulator setup
console.log(`🔧 Auth Emulator -> http://${host}:9099`);
getApp().functions('us-central1').useEmulator(host, 5001);
console.log(`🔧 Functions Emulator -> ${host}:5001 (region: us-central1)`);
} catch (error) {
console.error("❌ Error connecting to Firebase Emulators:", error);
}
}
}, []);
*/
Relevant Backend Code Snippet (functions/index.js
):
const { onCall, HttpsError } = require("firebase-functions/v2/https"); // Added HttpsError import
const logger = require("firebase-functions/logger");
// const admin = require("firebase-admin"); // Not needed for the basic onCall check
// admin.initializeApp(); // Initializes correctly in live, has issues detecting AUTH emulator env var
exports.updateDopamineState = onCall({ region: 'us-central1' }, (request) => {
logger.info("updateDopamineState called. Verifications:", request.verifications);
// This check fails because request.auth is null/undefined
if (!request.auth) {
logger.error("[updateDopamineState] Authentication check failed! request.auth is falsy.", { auth: request.auth });
throw new HttpsError('unauthenticated', 'The function must be called while authenticated.');
}
const userId = request.auth.uid;
logger.info(`Authenticated user: ${userId}`);
// ... rest of the function logic ...
// Example response
return { success: true, message: `State updated for ${userId}` };
});
// Test function without auth check (works via httpsCallable from client to emulator)
exports.testNoAuth = onCall({ region: 'us-central1' }, (request) => {
logger.info("testNoAuth called. Data:", request.data);
return { success: true, message: "Hello from testNoAuth!" };
});
Project Files
Javascript
Click To Expand
package.json
:
{
"name": "dopameter",
"license": "0BSD",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@notifee/react-native": "^9.1.8",
"@react-native-async-storage/async-storage": "^2.1.2",
"@react-native-community/cli-plugin-metro": "^12.3.6",
"@react-native-community/datetimepicker": "^8.3.0",
"@react-native-community/netinfo": "^11.4.1",
"@react-native-firebase/app": "^21.14.0",
"@react-native-firebase/auth": "^21.14.0",
"@react-native-firebase/firestore": "^21.14.0",
"@react-native-firebase/functions": "^21.14.0",
"@react-native-firebase/messaging": "^21.14.0",
"@react-navigation/native": "^7.0.14",
"@react-navigation/stack": "^7.1.1",
"cors": "^2.8.5",
"firebase": "^11.4.0",
"hermes-engine": "^0.11.0",
"metro-react-native-babel-transformer": "^0.77.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-native": "0.78.0",
"react-native-calendars": "^1.1310.0",
"react-native-chart-kit": "^6.12.0",
"react-native-foreground-service": "^1.0.0",
"react-native-gesture-handler": "^2.24.0",
"react-native-linear-gradient": "^2.8.3",
"react-native-progress": "^5.0.1",
"react-native-reanimated": "^3.17.1",
"react-native-safe-area-context": "^5.3.0",
"react-native-screens": "^4.9.2",
"react-native-svg": "^15.11.2",
"react-native-svg-transformer": "^1.5.0",
"react-native-tab-view": "^4.0.5",
"react-native-vector-icons": "^10.2.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/preset-flow": "^7.25.9",
"@babel/preset-react": "^7.26.3",
"@react-native-community/cli": "^15.0.0",
"@react-native-community/cli-platform-android": "^11.0.0",
"@react-native/gradle-plugin": "^0.78.0",
"@react-native/metro-config": "^0.78.0",
"metro-react-native-babel-preset": "^0.77.0",
"patch-package": "^8.0.0",
"react-native-dotenv": "^3.4.11"
},
"private": true,
"overrides": {
"metro": "0.78.0",
"metro-config": "0.78.0",
"metro-core": "0.78.0",
"metro-runtime": "0.78.0",
"metro-resolver": "0.78.0",
"metro-transform-worker": "0.78.0"
},
"scripts": {
"postinstall": "patch-package"
}
}
// NOTE: Please also add the firebase-admin version from your functions/package.json
// (Assuming functions/package.json has firebase-admin and firebase-functions)
firebase.json
for react-native-firebase v6:
{
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log",
"*.local"
]
}
],
"emulators": {
"auth": {
"port": 9099
},
"functions": {
"port": 5001
},
"ui": {
"enabled": true
},
"singleProjectMode": true
}
}
iOS
Click To Expand
ios/Podfile
:
- I'm not using Pods
- I'm using Pods and my Podfile looks like:
# --- PASTE YOUR Podfile HERE IF APPLICABLE ---
# N/A (if not targeting iOS or not relevant)
AppDelegate.m
:
// --- PASTE YOUR AppDelegate.m HERE IF APPLICABLE ---
// N/A (if not targeting iOS or not relevant)
Android
Click To Expand
Have you converted to AndroidX?
- my application is an AndroidX application?
- I am using
android/gradle.settings
jetifier=true
for Android compatibility? - I am using the NPM package
jetifier
for react-native compatibility?
android/build.gradle
:
// --- PASTE YOUR android/build.gradle HERE ---
// N/A (Please provide if possible)
android/app/build.gradle
:
// --- PASTE YOUR android/app/build.gradle HERE ---
// N/A (Please provide if possible, especially dependencies section)
android/settings.gradle
:
// --- PASTE YOUR android/settings.gradle HERE ---
// N/A (Please provide if possible)
MainApplication.java
:
// --- PASTE YOUR MainApplication.java HERE ---
// N/A (Please provide if possible)
AndroidManifest.xml
:
<!-- --- PASTE YOUR AndroidManifest.xml HERE --- -->
<!-- N/A (Please provide if possible) -->
Environment
Click To Expand
react-native info
output:
System:
OS: Windows 11 10.0.26100
CPU: (12) x64 Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
Memory: 776.73 MB / 15.91 GB
Binaries:
Node:
version: 20.18.3
path: C:\Program Files\nodejs\node.EXE
Yarn:
version: 1.22.19
path: ~\AppData\Roaming\npm\yarn.CMD
npm:
version: 11.3.0
path: C:\Program Files\nodejs\npm.CMD
Watchman: Not Found
SDKs:
Android SDK:
API Levels:
"33"
"34"
"35"
Build Tools:
30.0.3
33.0.0
33.0.2
34.0.0
34.0.0
34.0.0
34.0.0
35.0.0
35.0.0
35.0.0
35.0.0
35.0.0
36.0.0
System Images:
android-35 | Google Play Intel x86_64 Atom
Android NDK: Not Found
Windows SDK:
AllowAllTrustedApps: Disabled
IDEs:
Android Studio: AI-242.23726.103.2422.13103373
Visual Studio: Not Found
Languages:
Java: 17.0.12
Ruby: Not Found
npmPackages:
"@react-native-community/cli":
installed: 15.1.3
wanted: ^15.0.0
react:
installed: 19.0.0
wanted: 19.0.0
react-native:
installed: 0.78.0
wanted: 0.78.0
react-native-windows: Not Found
npmGlobalPackages:
"react-native": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: Not found
newArchEnabled: Not found
- Platform that you're experiencing the issue on:
- iOS
- Android
- iOS but have not tested behavior on Android
- Android but have not tested behavior on iOS
- Both
react-native-firebase
version you're using that has this issue:21.14.0
Firebase
module(s) you're using that has the issue:Auth
,Functions
- Are you using
TypeScript
?N
- 👉 Check out
React Native Firebase
andInvertase
on Twitter for updates on the library.