0
votes

I'm working with a project using PHP and need to implement Google Cloud APIs using PHP Client library, but the authentication does not seem to be working for me. I have created a service account and granted the project owner permissions and I don't want to make authentication by using the GOOGLE_DEFAULT_CREDENTIALS environment variable, I want to use service account authentication.

Here's what I have tried:

require 'vendor/autoload.php';
use Google\Cloud\Core\ServiceBuilder;
use Google\Cloud\Storage\StorageClient;

// Authentication with Google Cloud Platform
$client = new ServiceBuilder([
    'keyFilePath' => 'api-project-374381085870-eaf930d9ffd7.json'
]);
$client = new StorageClient();
$bucket = $client->bucket('storage_client');

// Upload a file to the bucket.
$bucket->upload(
    fopen('file.txt', 'r')
);

But it returns an error as:

Warning: file_get_contents(/Users/abdul/.config/gcloud/application_default_credentials.json): failed to open stream: Permission denied in /Applications/XAMPP/xamppfiles/htdocs/storage/vendor/google/auth/src/CredentialsLoader.php on line 102

Warning: file_get_contents(/Users/abdul/.config/gcloud/application_default_credentials.json): failed to open stream: Permission denied in /Applications/XAMPP/xamppfiles/htdocs/storage/vendor/google/auth/src/CredentialsLoader.php on line 102

Fatal error: Uncaught exception 'Google\Cloud\Core\Exception\ServiceException' with message '{ "error": { "errors": [ { "domain": "global", "reason": "authError", "message": "Invalid Credentials", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Invalid Credentials" } } ' in /Applications/XAMPP/xamppfiles/htdocs/storage/vendor/google/cloud-core/src/RequestWrapper.php:263 Stack trace: #0 /Applications/XAMPP/xamppfiles/htdocs/storage/vendor/google/cloud-core/src/RequestWrapper.php(168): Google\Cloud\Core\RequestWrapper->convertToGoogleException(Object(GuzzleHttp\Exception\ClientException))

1 /Applications/XAMPP/xamppfiles/htdocs/storage/vendor/google/cloud-core/src/Upload/MultipartUploader.php(65):

Google\Cloud\Core\RequestWrapper->send(Object(GuzzleHttp\Psr7\Request), Array) #2 /Applications/XAMPP/xamppfiles/htdocs/storage/vendor/google/cloud-storage/src/Bucket.php(283): Google\Cloud\Core\Upload\MultipartUploader->upload() #3 /Applications/XAMPP/xamppf in /Applications/XAMPP/xamppfiles/htdocs/storage/vendor/google/cloud-core/src/RequestWrapper.php on line 263

Help me, please!

Thanks in advance!

2
Provide your keyFilePath to the class which you are actually using. The ServiceBuilder instantiation is unnecessary here. new StorageClient(['keyFilePath' => '...']);jdp
Hi @jdp, thanks, it's working... you can post an answer if you want.Abdul Rehman
great! glad it worked. :)jdp

2 Answers

2
votes

The keyfile configuration must be provided to the client which is being called. The ServiceBuilder is often convenient because it allows you to create a single instance with your configuration, and that configuration is passed to each new client.

In your example, you've created a ServiceBuilder instance with a keyfile, but you're not using that instance to call Storage.

Two options:

use Google\Cloud\Core\ServiceBuilder;

$cloud = new ServiceBuilder([
    'keyFilePath' => 'my-keyfile.json'
]);

$storage = $cloud->storage();

or

use Google\Cloud\Storage\StorageClient;

$storage = new StorageClient([
    'keyFilePath' => 'my-keyfile.json'
]);

In both examples, $storage should be authenticated and ready to use!

0
votes

This issue is being generated due to the way you are creating the StorageClient object and specifying the the private key file parameter.

You can find the following example to Pass the path to the service account key in code on Google Cloud Platform site that is a very useful reference for your issue:

namespace Google\Cloud\Samples\Auth;

// Imports the Google Cloud Storage client library.
use Google\Cloud\Storage\StorageClient;

function auth_cloud_explicit($projectId, $serviceAccountPath)
{
    # Explicitly use service account credentials by specifying the private key
    # file.
    $config = [
        'keyFilePath' => $serviceAccountPath,
        'projectId' => $projectId,
    ];
    $storage = new StorageClient($config);

    # Make an authenticated API request (listing storage buckets)
    foreach ($storage->buckets() as $bucket) {
        printf('Bucket: %s' . PHP_EOL, $bucket->name());
    }
}