iosswiftrecaptcha-v3recaptcha-enterprise

INVALID_ARGUMENT when sending V3 reCAPTCHA token for assessment


We are getting an error when sending reCAPTCHA tokens for assessment.

The token is produced on the client using the RecaptchaEnterprise.xcframework and should be sent from our backend to Google.

This is the code that instantiate the client:

    private func activateReCAPTCHA() {
    _Concurrency.Task {
        if #available(iOS 14.0, *) {
            let (recaptchaClient, error) = await Recaptcha.getClient(Resources.recaptchaKey)
            if let error {
                print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
                error.reportToExternalServices()
            } else if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
                appDelegate.recaptchaClient = recaptchaClient
                print("RecaptchaClient created.")
            } else {
                print("RecaptchaClient creation error: AppDelegate not available.")
            }
            sleep(0)
        }
    }
}

This is the code that requests and receives the token:

extension RecaptchaClient {
    static var client: RecaptchaClient? {
        if #available(iOS 14.0, *) {
            return (UIApplication.shared.delegate as? AppDelegate)?.recaptchaClient
        } else {
            return nil
        }
    }
}

private func fetchReCAPTCHAToken() {
    guard let recaptchaClient = RecaptchaClient.client else {
        print("fetchReCAPTCHAToken: RecaptchaClient not found")
        return
    }
    
    if #available(iOS 14.0, *) {
        Task {
            let (token, error) = await recaptchaClient.execute(RecaptchaAction(action: .login))
            if let token = token {
                print("fetchReCAPTCHAToken: \(token.recaptchaToken)")
            } else {
                print("fetchReCAPTCHAToken: \(String(describing: error?.errorMessage))")
            }
            sleep(0)
        }
    }
}

So far everything is good. To simulate the backend, I created a cURL script that sends the following json, with the generated token pasted from the xCode console:

  {
      "event": {
          "token": "...",
          "siteKey": "...",
          "expectedAction": "login"
      }
  }

The method is POST and the URL is of the following structure:

https://recaptchaenterprise.googleapis.com/v1/projects/.../assessments?key=...

The response:

{

  "error": {
      "code": 400,

      "message": "Request contains an invalid argument.",

      "status": "INVALID_ARGUMENT"
  }
}

We did the same with Postman and had the same result. What might be the reason for that?

---- Update ----

We were finally able to get a valid response by doing the following:

  1. Log into the Google Cloud console
  2. From the CLI, run a cURL to the following address: "https://recaptchaenterprise.googleapis.com/v1/projects/.../assessments?access_token=$(gcloud auth print-access-token)"

When compared to the previous attempts, the only difference is that the CLI script uses an OAUTH2 access_token= instead of a key=. So we conclude that the problem is probably in the key= argument. The value we are using for the key= argument is the secret key that has the following description: Use this secret key for communication between your site and reCAPTCHA. The question is still open for anyone who has a clue.


Solution

  • I would double check your siteKey argument. Note this should be your reCAPTCHA Enterprise site key, not a GCP API key. Nor is it your "private" key if you migrated from reCAPTCHA v2 or v3 to reCAPTCHA Enterprise.

    Note that the ?key= query param in the request is the API key though if this was not correct it would manifest as an auth error, not an invalid argument.