Search code examples
flutterfirebasegoogle-cloud-functionsfirebase-app-check

Firebase cloud function with AppCheck failing with 401 - Unauthorized


I just deployed my first flutter web app with a Firebase cloud function called "createCompany". The function works fine when running against the Firebase emulators, but fails with an (unhelpful) error when deployed live:

Cloud console error log:

2023-04-29 12:32:42.138 MST createCompany 17d1f7wc8kv1 Function execution started

2023-04-29 12:32:42.144 MST createCompany 17d1f7wc8kv1 Callable request verification passed

2023-04-29 12:32:42.145 MST createCompany 17d1f7wc8kv1 Function execution took 7ms, finished with status: 'error'

The Chrome developer console's Network Monitor shows an invocation of createCompany with a response of 401 - Unauthorized.

I set up AppCheck and this appears to be the source of the problem. When I redeploy after removing enforceAppCheck from the cloud function, it runs successfully.

Setup in main:

  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  AndroidProvider provider = AndroidProvider.playIntegrity;
  if (kDebugMode) {
    provider = AndroidProvider.debug;
  }
  await FirebaseAppCheck.instance.activate(
    webRecaptchaSiteKey: '<My actual site key here>',
    androidProvider: provider,
  );

Invocation in flutter

Future<String> createCompany(String firstName, String lastName) async {
        var result = await FirebaseFunctions.instance
            .httpsCallable('createCompany')
            .call(<String, dynamic>{'firstName': firstName, 'lastName': lastName});
        return result.data["company"];
      }

Cloud function:

     exports.createCompany = functions.runWith({
          enforceAppCheck: true
        })
          .https.onCall(async (data, context) => {
        
            functions.logger.log("createCompany start");
        
            if (context.app == undefined) {
              throw new functions.https.HttpsError(
                'failed-precondition',
                'The function must be called from an App Check verified app.')
            }
... //Function logic

Cloud console settings for invoker:

Cloud console settings

My reCAPTCHA secret key has been entered in the Firebase console.

What else do I need to do to make this work in production?


Solution

  • There were two problems that were preventing AppCheck from working.

    First, I spaced the fact that "firebase deploy" builds your cloud functions, but it does NOT build your flutter app, so code changes to my app were not being deployed. I needed to run "flutter build web" first.

    Second, in the Firebase console -> Authentication -> Settings -> Authorized Domains, there is a list of domains. All those domains must be added to reCAPTCHA. I had 3 out of 4. The Firebase generated one I didn't add is probably used to send the requests used by AppCheck.

    Once I addresses those two issues, AppCheck started working for all my cloud functions and real time database requests. Hope this helps!