2

I'm getting a "Could not construct ApplicationDefaultCredentials" from Google Recaptcha Enterprise, but only on our remote server. I've tried everything I can think of to isolate the issue, but I've had no luck.

I have two Recaptcha Enterprise keys: One for testing, and one for prod.

The testing key works fine on localhost. I've tried both the testing and prod key on our staging server, but I keep getting the same error.

Could not construct ApplicationDefaultCredentials

Things I've checked:

  • The key is successfully requesting tokens (I can see them in the form)
  • The service account .json credentials are being picked up correctly (I've tried outputting the contents to ensure they can be read)
  • The domains are correctly configured and allowed (Google helpfully lets you know if this isn't the case)
  • The Project ID is also correctly being picked up and sent

Basically all the values are present (project ID, site ID, service account details) and the domain is allowed, but as soon as it's on the remote staging server, it is failing to create credentials.

I'm struggling to figure out what the difference could be.

public static function createRecaptchaAssessment(
    string $siteKey, // Present
    string $token, // Present
    string $projectId // Present
): Assessment {
    $options = [
        'keyFile' => config('services.google.app_credentials'), // Present
        'projectID' => $projectId
    ];

    $client = new RecaptchaEnterpriseServiceClient($options); // <-- Throws exception for ApplicationDefaultCredentials not being able to be created

...

Things to consider: The staging server is hosted on an elasticbeanstalk.com subdomain, and the site is password protected with .htpasswd. I know sometimes elasticbeanstalk.com is blacklisted because it is a blanket domain, but we're only specifying the subdomain and there's no "This domain is not allowed" message from Google. And there shouldn't be any inbound connections being blocked by .htapasswd that I'm aware of.

I've tried creating a new Service Account, just incase there was something configured incorrectly (it has Recaptcha Enterprise Agent permissions) but nothing changed.

Any ideas on how else I could debug this would be gratefully appreciated. (Note: This is a PHP/Laravel 9 project hosted on AWS Elastic Beanstalk, but I don't think that's a factor.)

1 Answer 1

3

Key takeaway: The ApplicationDefaultCredentials error is almost certainly related to the Service Account .json not being picked up by your application.

Full version: So apparently I took some poor advice from another SO answer which suggested you could pass the path to the Service Account credentials .json file through the following array:

$options = [
    'keyFile' => config('services.app_credentials'), // DON'T DO THIS
    'projectID' => $projectId
];

I spent a long time looking through the Google library only to discover that neither array keys are used. Actually what happens is this:

If the library isn't passed a path to the Service Account credentials .json file, it then looks for an environment variable called GOOGLE_APPLICATION_CREDENTIALS.

If you have this ENV and your environment supports it, that's actually what it is going on. (Which is why you might find that it works locally, but not remotely, as I did.)

When you deploy Laravel remotely, all the .env variables are cached and so not available through getenv()... meaning the library is not able to find GOOGLE_APPLICATION_CREDENTIALS even if you have it included in your .env.

The solution is to add the path through an array key credentials:

$options = [
    'credentials' => config('services.app_credentials')
];

$client = new RecaptchaEnterpriseServiceClient($options);

Now it works perfectly.

Not the answer you're looking for? Browse other questions tagged or ask your own question.