3

I am calling a cloud function which runs a transaction, however it is returning an error to console which says:

Callable request verification passed {"verifications":{"auth":"VALID","app":"MISSING"}}

Googling it led me to App Check which is a new thing in Firebase. I am using React-Native firebase npm packages and following its documentation about App Check is extremely difficult due to lack of proper explanation and examples.

Below I have the code which I am trying to execute in the function:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
const firestore_ = admin.firestore();
// const { CustomProvider } = require("@react-native-firebase/app-check");
const appCheckForDefaultApp = admin.appCheck();    
const GeoPoint = admin.firestore.GeoPoint;
const FieldValue = admin.firestore.FieldValue;    
const _geofirestore_ = require("geofirestore");
const GeoFirestore = _geofirestore_.initializeApp(firestore_);



exports.createNew = functions.runWith({
   allowInvalidAppCheckToken: true  // Opt-out: Requests with invalid App
   // Check tokens continue to your code.
}).region('europe-west6').https.onCall(async (data, context) => {

   try {

      //Checking that the user calling the Cloud Function is authenticated
      if (!context.auth) {
         return "The user is not authenticated: " + context.auth;
         // throw new UnauthenticatedError('The user is not authenticated. Only authenticated Admin users can create new users.');
      }

      const longitude = data.longitude;
      const latitude = data.latitude;
      const thirty_mins_old = data.thirty_mins_old;
      const currenttime = data.currenttime;

      const GeoFirestore_ = new _geofirestore_.GeoFirestore(firestore_);
      const sfDocRef = GeoFirestore_.collection('mycollection')
         .limit(1)
         .near({ center: new GeoPoint(latitude, longitude), radius: 0.05 });

      GeoFirestore.runTransaction((transaction) => {
         const geotransaction = new _geofirestore_.GeoTransaction(transaction, new GeoPoint(latitude, longitude));
         return geotransaction.get(sfDocRef._collectionPath).then((sfDoc) => {
            ...
         });
      });

   } catch (error) {
      if (error.type === 'UnauthenticatedError') {
         throw new functions.https.HttpsError('unauthenticated', error.message);
      } else if (error.type === 'NotAnAdminError' || error.type === 'InvalidRoleError') {
         throw new functions.https.HttpsError('failed-precondition', error.message);
      } else {
         throw new functions.https.HttpsError('internal', error.message);
      }
   }
});

EDIT: I am debugging the app so I am not working on production. Does debugging still requires this to be configured?

showtime
  • 1
  • 1
  • 17
  • 48

1 Answers1

3

The log message you are seeing is not an error - it's informational.

On each request, your callable functions will verify any auth or appcheck token included in the request. When these tokens are not present, the execution is passed to your handler - it's your responsibility to handle requests with missing tokens if necessary. It looks like you are already handling the case for missing auth token.

When executing functions in your auth emulator, auth/appcheck tokens are minimally verified - i.e. they should be valid JWT token but we don't actually verify the signature to ensure that it's signed by Firebase Auth/AppCheck backend.

If your function is erroring in your development environment, I suspect that the error is elsewhere.

Daniel L
  • 450
  • 3
  • 6
  • 1
    if that just a warning, why then there is this flag allowInvalidAppCheckToken to allow the invalid app check tokens? I mean there is no need for it if this check is not really required, right? – showtime Feb 26 '22 at 16:29
  • 1
    @showtime Think of it this way - there are 3 possible result when verifying AppCheck tokens; VALID, MISSING, and INVALID. Without the `allowInvalidAppCheckToken` flag, the control is passed to your handler in VALID and MISSING state. With the flag, the control is passed to your handler in all 3 cases (you decide what to do in case of INVALID token). – Daniel L Feb 28 '22 at 17:03