Skip to content

[πŸ›] App Check token not attached to Firestore requests on Android β€” firestore/permission-denied (v24.0.0)Β #9007

@Vasudevan-iOS

Description

@Vasudevan-iOS

Bug Report

Describe the bug

After successfully initializing Firebase App Check and receiving a valid JWT token via getToken(), Firestore write requests still fail with firestore/permission-denied when App Check enforcement is enabled in the Firebase Console.

The App Check token is fetched correctly β€” it is a proper JWT string (200+ characters starting with eyJ). However, the token is not being attached to outgoing Firestore requests by the native SDK on Android. The Firestore client fires its request without the App Check token header, causing Firebase to reject it.

This issue is specific to Android. The JS layer behaves correctly β€” the problem is in the native bridge not forwarding the token to the Firestore client before the request fires.


Steps to Reproduce

  1. Initialize App Check with ReactNativeFirebaseAppCheckProvider using debug provider on Android
  2. Register the debug token in Firebase Console β†’ App Check β†’ Android app β†’ Manage debug tokens
  3. Enable App Check enforcement in Firebase Console
  4. Set Firestore rule: allow read, write: if request.app != null;
  5. Call getToken(appCheckInstance, true) β€” token is returned successfully (valid JWT)
  6. Immediately perform a Firestore setDoc() write
  7. Write fails with firestore/permission-denied

Note: If Firestore rule is changed to allow read, write: if true, the write succeeds β€” confirming the code, project config, and network are all correct. Only the App Check token attachment is broken.


Expected Behavior

After getToken() resolves with a valid token, the native Firestore client should automatically attach the App Check token to all subsequent requests without any manual intervention.


Actual Behavior

getToken() resolves with a valid JWT token, but Firestore requests are sent without the App Check token attached. Firebase enforces App Check and rejects the request with:

[firestore/permission-denied] The caller does not have permission to execute the specified operation.

Reproducible Sample Code

appCheck.ts

import { getApp } from '@react-native-firebase/app';
import { initializeAppCheck, getToken } from '@react-native-firebase/app-check';

const { ReactNativeFirebaseAppCheckProvider } = require('@react-native-firebase/app-check');

let appCheckInstance = null;

export const initializeFirebaseAppCheck = async () => {
  const provider = new ReactNativeFirebaseAppCheckProvider();
  provider.configure({
    android: {
      provider: __DEV__ ? 'debug' : 'playIntegrity',
      debugToken: 'YOUR-DEBUG-TOKEN-UUID',
    },
  });

  appCheckInstance = await initializeAppCheck(getApp(), {
    provider,
    isTokenAutoRefreshEnabled: true,
  });
};

export const ensureAppCheckReady = async () => {
  if (!appCheckInstance) throw new Error('AppCheck not initialized');
  return appCheckInstance;
};

feedbackService.ts

import { getFirestore, collection, doc, setDoc } from '@react-native-firebase/firestore';
import { getApp } from '@react-native-firebase/app';
import { getToken } from '@react-native-firebase/app-check';
import { ensureAppCheckReady } from './appCheck';

export const submitFeedback = async () => {
  const appCheckInstance = await ensureAppCheckReady();
  const { token } = await getToken(appCheckInstance, true);

  // token is a valid JWT here β€” confirmed via logging
  console.log('Token:', token); // eyJraWQiOiJrMnhhbUEi...

  const db = getFirestore(getApp());
  const docRef = doc(collection(db, 'test-collection'));

  // This fails with firestore/permission-denied even though token is valid
  await setDoc(docRef, { test: true });
};

Firestore Rule (enforced)

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.app != null;
    }
  }
}

Device Information

  • Device: Samsung SM-M526B
  • Android OS: 13
  • Build type: Debug (__DEV__ === true)
  • App Check provider: debug (not Play Integrity)

Environment

System:
  OS: macOS
  
React Native: 0.80.1
Node: v25.9.0

@react-native-firebase/app: 24.0.0
@react-native-firebase/app-check: 24.0.0
@react-native-firebase/firestore: 24.0.0

Additional Context

  • App Check is set to Enforced (not Monitoring) in Firebase Console
  • Debug token is correctly registered in Firebase Console β†’ App Check β†’ Android app β†’ Manage debug tokens
  • google-services.json project_id matches the Firebase Console project exactly
  • Firestore database is the default (default) database
  • The issue does not occur when Firestore rule is if true β€” confirming the write path works
  • Adding a setTimeout delay (300–1000ms) after getToken() before the Firestore write does not resolve the issue
  • This appears to be a native bridge propagation issue where the Android Firestore client does not pick up the App Check token before firing requests

Possible Fix

The App Check token returned by getToken() is not being automatically registered with the native Firestore client in v24.0.0. This worked correctly in earlier versions. The native Android layer needs to forward the token to the Firestore SDK before any request is dispatched.

System Info

System:
OS: macOS 26.4.1
CPU: (18) arm64 Apple M5 Pro
Memory: 105.20 MB / 24.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 25.9.0
path: /opt/homebrew/bin/node
Yarn:
version: 1.22.22
path: /opt/homebrew/bin/yarn
npm:
version: 11.12.1
path: /opt/homebrew/bin/npm
Watchman:
version: 2026.04.20.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.15.2
path: .rbenv/shims/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 25.4
- iOS 26.4
- macOS 26.4
- tvOS 26.4
- visionOS 26.4
- watchOS 26.4
IDEs:
Android Studio: 2025.3 AI-253.31033.145.2533.15176040
Xcode:
version: 26.4.1/17E202
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.18
path: /usr/bin/javac
Ruby:
version: 3.2.2
path: rbenv/shims/ruby
npmPackages:
"@react-native-community/cli":
installed: 19.0.0
wanted: 19.0.0
react:
installed: 19.1.0
wanted: 19.1.0
react-native:
installed: 0.80.1
wanted: 0.80.1
react-native-macos: Not Found
npmGlobalPackages:
"react-native": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: true
newArchEnabled: true

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions