swift – Getting invalid firebase app check token in IOS device and simulator


I am trying to call ChatGPT api in firebase cloud function with app check validation. I want to use “App Attest” as validation method. I have done all the setup and coding as mentioned in the Firebase app check doc but still I am getting invalid app check token error.

Here is what I have tried:

Physical device

  1. Entitlement
    Set App Attest Env to “production”

  2. Added App Attest in capability
    (https://i.stack.imgur.com/b07wz.png)

  3. Enabled App Attest in Firebase console after adding Apple team id
    (https://i.stack.imgur.com/IgeuU.png)

  4. Configuration code in App Delegate

class AppDelegate: NSObject, UIApplicationDelegate {
  func application(_ application: UIApplication,
                   didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    
      let providerFactory = YourAppCheckProviderFactory()
//      let providerFactory = AppCheckDebugProviderFactory()
      AppCheck.setAppCheckProviderFactory(providerFactory)
      FirebaseApp.configure()
    return true
  }
}

class YourAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
  func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
    return AppAttestProvider(app: app)
//      return DeviceCheckProvider(app: app)
  }
}
  1. Here is my Firebase function which I am trying to call from swift and which subsequently calls ChatGPT API upon successful validation of app check token
exports.callGPT = functions.https.onRequest(async (request, response) => {
  try {
    // Validate Firebase App Check token
    const appCheckToken = request.headers["x-firebase-appcheck"];
    if (!appCheckToken) {
      return response.status(401)
          .send("Unauthorized: App Check token missing");
    }

    // const appCheckResponse = await getAppCheck().verifyToken(appCheckToken);
    const appCheckResponse = await admin.appCheck()
        .verifyToken(appCheckToken);
    if (!appCheckResponse.valid) {
      return response.status(401)
          .send("Unauthorized: Invalid App Check token");
    }

    // Replace "YOUR_CHATGPT_API_KEY" with your actual ChatGPT API key
    const chatGPTApiKey = "sk-token";

    // Extract the input text from the request body
    // const inputText = "Hi";
    const inputText = request.body.text;

    // Make a request to the ChatGPT API
    const chatGPTResponse = await axios.post(
        "https://api.openai.com/v1/chat/completions",
        {
          model: "gpt-3.5-turbo",
          messages: [{role: "system", content: "You are a helpful assistant."},
            {role: "user", content: inputText}],
        },
        {
          headers: {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + chatGPTApiKey,
          },
        },
    );

    // Extract the response from ChatGPT
    const chatGPTOutput = chatGPTResponse.data.choices[0].message.content;

    // Send the ChatGPT output as the response
    response.status(200).send({output: chatGPTOutput});
  } catch (error) {
    console.error("Error calling ChatGPT API:", error);
    response.status(500).send("Internal Server Error");
  }
});
  1. This is my swift code which calls cloud function
func sendPrompt() async {
        showLoader = true
        AppCheck.appCheck().token(forcingRefresh: false) { token, error in
            if let token = token {
                guard let url = URL(string: "baseurl/callGPT") else {
                    return
                }

                var request = URLRequest(url: url)

                request.httpMethod = "POST"
                request.setValue("application/json", forHTTPHeaderField: "Content-Type")
                request.setValue(token.token, forHTTPHeaderField: "X-Firebase-AppCheck")
                
                struct RequestObj: Codable, Hashable{
                    var text: String?
                }
                var requestObj = RequestObj(text: topic)
                let scriptData = try? JSONEncoder().encode(requestObj)
                request.httpBody = scriptData

                let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
                    if let error = error {
                        print("Error in app script: \(error)")
                    } else if let data = data, let responseString = String(data: data, encoding: .utf8) {
                        print("responseString = \(responseString)")
                        do {
                            struct ResponseObj: Codable, Hashable{
                                var output:String?
                            }
                            var responseObj = try JSONDecoder().decode(ResponseObj.self, from: data)
                            output = responseObj.output ?? ""
                            print("output = \(output)")
                        } catch {
                            print("an error occurred", error)
                        }
                    }
                    showLoader = false
                }

                task.resume()
            } else if let error = error {
                print ("AppCheck error: \(error as NSError).userInfo)")
            }
        }
    }

I have tried to run on my physical device but it gives “invalid app check token” error.

I also tried to run on Xcode simulator after doing the following changes

Xcode simulator

  1. in App Delegate
class AppDelegate: NSObject, UIApplicationDelegate {
  func application(_ application: UIApplication,
                   didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    
//      let providerFactory = YourAppCheckProviderFactory()
      let providerFactory = AppCheckDebugProviderFactory()
      AppCheck.setAppCheckProviderFactory(providerFactory)
      FirebaseApp.configure()
    return true
  }
}

class YourAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
  func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
    return AppAttestProvider(app: app)
//      return DeviceCheckProvider(app: app)
  }
}
  1. Added -FIRDebugEnabled in the Arguments Passed on Launch section
    (https://i.stack.imgur.com/P5f3O.png)

  2. Added debug token in firebase console
    (https://i.stack.imgur.com/bp7nd.png)

Kept code in point 5 & 6 same as above. Even after doing all the required changes I am not able to validate my app check token in cloud function

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img