googleapis / google-cloud-php

Google Cloud Client Library for PHP
https://cloud.google.com/php/docs/reference
Apache License 2.0
1.09k stars 436 forks source link

[Cloud Vision] Unable to authenticate by passing in key file #1661

Closed jryd closed 5 years ago

jryd commented 5 years ago

Other Google API PHP Client packages (e.g Datastore) allow you to pass in a key file to authenticate the client with. The readme for Cloud Vision links the authentication section to a page that specifies we can pass in a keyFile or keyFilePath to authenticate with rather than setting an environment variable. However, when trying to pass a keyFile or keyFilePath in, the client will not successfully authenticate and you will get a ValidationException for Could not construct ApplicationDefaultCredentials..

Environment details

Steps to reproduce

  1. Attempt to use the ImageAnnotator like below
  2. When running the code, observe that you get an error:

Could not construct ApplicationDefaultCredentials

Code example

new ImageAnnotatorClient([
    'keyFile' => json_decode(file_get_contents(__DIR__ . '/auth.json'), true)
    // OR  'keyFilePath' => __DIR__ . '/auth.json',
 ]);

The temporary workaround to get the API client has been to use the below:

putenv("GOOGLE_APPLICATION_CREDENTIALS=" . __DIR__ . '/auth.json');
$this->imageAnnotator = new ImageAnnotatorClient();

This isn't really a viable solution as my codebase interacts with a couple of different projects inside GCP, hence the need to be able to pass a key file.

jryd commented 5 years ago

Interestingly if you use the VisionClient instead of the ImageAnnotatorClient then you can pass in the key file without issue:

// This works
new VisionClient([
    'keyFilePath' => __DIR__ . '/auth.json',
]);
jdpedrie commented 5 years ago

Hi @jryd,

Keyfiles for clients such as Google\Cloud\Vision\V1\ImageAnnotatorClient may be provided using the credentials array key, like so:

use Google\Cloud\Vision\V1\ImageAnnotatorClient;

$v = new ImageAnnotatorClient([
    'credentials' => '/path/to/keyfile.json'
]);
dwsupplee commented 5 years ago

As @jdpedrie mentioned, there is a slightly different way to configure credentials for our generated clients vs. our manually written ones. We will be bridging this gap in the future so there is only need to know one set of configuration options :).

acidjazz commented 4 years ago

Not sure why this is a closed issue, also not finding this anywhere in the documentation or examples. I'd suggest re-opening this and closing it either a. when you bridge the gap or b. document this somewhere @dwsupplee

kublermdk commented 4 years ago

I had this very issue and thought I'd blindly tried every combination of key, keyFile and credentials, however I thought that credentials was an object containing the keyFile, I hadn't tried just giving it a string to the .json key file.

The code provided https://github.com/googleapis/google-cloud-php/issues/1661#issuecomment-460649702 should as acidjazz says, be added to the documentation and examples.

$v = new ImageAnnotatorClient([
    'credentials' => '/path/to/keyfile.json'
]);

I'd also love to see more examples of outputting the results. Even with IDE autocompletion and the docs it's hard to know how to get all the data (I'm in the process of trying to replicate the usual JSON response using PHP which is dealing with the Protocol Buffers response from what I can tell.

Ploppy3 commented 4 years ago

@kublermdk You nailed it, thanks a lot, I just spent hours because I used the recommended keyFilename instead of credentials.

netwons commented 3 years ago

im not work OS: Ubuntu PHP version: 7.2.4 & laravel Package name and version: google/cloud-vision 0.19.1

$v = new ImageAnnotatorClient([ 'credentials' => '/path/to/keyfile.json' ]); say google:use export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/AIzaSyCOh_CZ4aYMMgmVw-22gBLY.json" but not work this is my code

$v = new ImageAnnotatorClient([
            'credentials'=>'key.json'
        ]);
//        $client->setAuthConfig('key.json');

        # the name of the image file to annotate
        $fileName = '2.png';

        # prepare the image to be annotated
        $image = file_get_contents($fileName);

        # performs label detection on the image file
        $response = $imageAnnotator->labelDetection($image);
        $labels = $response->getLabelAnnotations();

        if ($labels) {
            echo("Labels:" . PHP_EOL);
            foreach ($labels as $label) {
                echo($label->getDescription() . PHP_EOL);
            }
        } else {
            echo('No label found' . PHP_EOL);
        }
kublermdk commented 3 years ago

@netwons

im not work

That code is all over the place. You don't use the $v client.

putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentialsLocation); // This might work, but didn't for me.

$imageAnnotatorClient = new ImageAnnotatorClient([
    'credentials' => $credentialsLocation // this works for me
]);

$response = $imageAnnotator->textDetection($gsFilePath);
$textAnnotation = $response->getTextAnnotations();

// -- Full JSON output
echo ($textAnnotation->serializeToJsonString());

// -- Alternative option: Go through each of the entries to get just the data you want
$text = (array)$textAnnotation;

$textAnnotations = [];
foreach ($textAnnotation as $text) {

    $vertices = $text->getBoundingPoly()->getVertices();
    $bounds = [];
    foreach ($vertices as $vertex) {
        $bounds[] = ['x' => $vertex->getX(), 'y' => $vertex->getY()];
    }
    $textAnnotations[] = [
        'description' => $text->getDescription(),
        'boundingPoly' => [
            'vertices' => $bounds
        ]

    ];
}

echo (json_encode($textAnnotations));

Side note: When getting an AutoMlClient or PredictionServiceClient I only needed to set the environment.

emuung commented 1 year ago

I am testing with a simple code. But , "textDetection" doesn't run without an error message. can I know what is the problem?

  try {
        $imageAnnotatorClient = new ImageAnnotatorClient([
            'credentials' => 'key.json'
        ]);
        $image=file_get_contents($_FILES['image']['tmp_name']);
        $imageContent=base64_encode($image);
        echo "test1"; // printed

        $response = $imageAnnotatorClient->textDetection($imageContent);
        echo "test2"; //not printed
        $text = $response->getTextAnnotations();
        echo $text[0]->getDescription();

        if ($error = $response->getError()) {
            print('API Error: ' . $error->getMessage() . PHP_EOL);
        }

        $imageAnnotatorClient->close();
    } catch(Exception $e) {
        echo $e->getMessage();
    }