Isaac Isaiah
Isaac Isaiah

Reputation: 11

Having trouble with App Check firebase backend for authenticating users with permissions

I'm currently dealing with an iOS app that is already published to the App Store. I've been troubleshooting the past few days without success. Trying to get Firebase to recognize my App Check token. Everything is working when I set rules to:

// Allow access to deviceScans only when a valid App Check token is provided match /deviceScans/{deviceId} { allow read, write: if true; }

However, when I change it to:

// Allow access to deviceScans only when a valid App Check token is provided match /deviceScans/{deviceId} { allow read, write: if request.appCheckToken != null; }

I get "Missing or insufficient permissions".

Here are some of the steps I've taken:

  1. Registered DeviceCheck and App Attest in Firebase; correctly triple‑checked my key ID, team ID, and uploaded my .p8 file

  2. Enforced App Check under App Check request metrics after clicking Cloud Firestore in App Check

  3. Added the GoogleService-Info.plist to my Xcode project and double‑checked the correct bundle and project ID

With this test code I seem to be getting App Check tokens in my Xcode console:

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        FirebaseApp.configure()

        let providerFactory = DeviceCheckProviderFactory()
        AppCheck.setAppCheckProviderFactory(providerFactory)

        // ✅ Debugging App Check Token
        AppCheck.appCheck().token(forcingRefresh: true) { token, error in
            if let error = error {
                print("❌ Error getting App Check token: \(error.localizedDescription)")
            } else if let token = token {
                print("✅ Got App Check token: \(token.token)")
            }
        }

        // ✅ Authenticate and then call Firestore test
        authenticateUserAndTestFirestore()
        testFirestoreAccess()

        return true
    }
}

The console reads "✅ Got App Check token"; however, with further testing of another function:

func testFirestoreAccess() {
    let db = Firestore.firestore()
    let testDocRef = db.collection("deviceScans").document("test-doc")

    testDocRef.getDocument { document, error in
        if let error = error {
            print("❌ Firestore access error: \(error.localizedDescription)")
        } else if let document = document, document.exists {
            print("✅ Firestore document retrieved: \(document.data() ?? [:])")
        } else {
            print("❌ Document does not exist")
        }
    }
}

I get ❌ Firestore access error: Missing or insufficient permissions. It seems my users don't get permission to read or write on my Firestore Database 'if request.appCheckToken != null'. This is critical for paying customers who rely on those database operations to fully unlock the app’s paid features.

Right now, I’ve had to revert to using 'allow read, write: if true' just to keep the app functional, but I’d like to properly enforce App Check instead.

After many days of troubleshooting, I am out of ideas as to why App Check is not functioning. If anyone can shed some light, I would greatly appreciate it. Thanks!

Upvotes: 1

Views: 50

Answers (1)

Volodymyr Kuzomenskyi
Volodymyr Kuzomenskyi

Reputation: 540

You call a function with completion block and do not use the value returned. Instead you try to call the token out of the completion block which is called before the completion block. So the token is there but you call it before it's available

Please try this instead:

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        FirebaseApp.configure()

        let providerFactory = DeviceCheckProviderFactory()
        AppCheck.setAppCheckProviderFactory(providerFactory)

        // ✅ Debugging App Check Token
        AppCheck.appCheck().token(forcingRefresh: true) { token, error in
            if let error = error {
                print("❌ Error getting App Check token: \(error.localizedDescription)")
            } else if let token = token {
                print("✅ Got App Check token: \(token.token)")
                // ✅ Authenticate and then call Firestore test
                authenticateUserAndTestFirestore()
                testFirestoreAccess()
            }
        }

        return true
    }
}

Upvotes: 1

Related Questions