Skip to content

Commit c9995b7

Browse files
authored
feat: allow credentials object (#2153)
1 parent 7db9eb4 commit c9995b7

File tree

2 files changed

+92
-15
lines changed

2 files changed

+92
-15
lines changed

src/Client.php

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ class Client
8686
*/
8787
private $logger;
8888

89+
/**
90+
* @var CredentialsLoader $credentials
91+
*/
92+
private $credentials;
93+
8994
/**
9095
* @var boolean $deferExecution
9196
*/
@@ -114,8 +119,9 @@ public function __construct(array $config = array())
114119
'client_id' => '',
115120
'client_secret' => '',
116121

117-
// Path to JSON credentials or an array representing those credentials
118-
// @see Google\Client::setAuthConfig
122+
// Can be a path to JSON credentials or an array representing those
123+
// credentials (@see Google\Client::setAuthConfig), or an instance of
124+
// Google\Auth\CredentialsLoader.
119125
'credentials' => null,
120126
// @see Google\Client::setScopes
121127
'scopes' => null,
@@ -175,7 +181,11 @@ public function __construct(array $config = array())
175181
);
176182

177183
if (!is_null($this->config['credentials'])) {
178-
$this->setAuthConfig($this->config['credentials']);
184+
if ($this->config['credentials'] instanceof CredentialsLoader) {
185+
$this->credentials = $this->config['credentials'];
186+
} else {
187+
$this->setAuthConfig($this->config['credentials']);
188+
}
179189
unset($this->config['credentials']);
180190
}
181191

@@ -405,42 +415,52 @@ public function createAuthUrl($scope = null)
405415
*/
406416
public function authorize(ClientInterface $http = null)
407417
{
408-
$credentials = null;
409-
$token = null;
410-
$scopes = null;
411418
$http = $http ?: $this->getHttpClient();
412419
$authHandler = $this->getAuthHandler();
413420

414421
// These conditionals represent the decision tree for authentication
415-
// 1. Check for Application Default Credentials
416-
// 2. Check for API Key
422+
// 1. Check if a Google\Auth\CredentialsLoader instance has been supplied via the "credentials" option
423+
// 2. Check for Application Default Credentials
417424
// 3a. Check for an Access Token
418425
// 3b. If access token exists but is expired, try to refresh it
426+
// 4. Check for API Key
427+
if ($this->credentials) {
428+
return $authHandler->attachCredentials(
429+
$http,
430+
$this->credentials,
431+
$this->config['token_callback']
432+
);
433+
}
434+
419435
if ($this->isUsingApplicationDefaultCredentials()) {
420436
$credentials = $this->createApplicationDefaultCredentials();
421-
$http = $authHandler->attachCredentialsCache(
437+
return $authHandler->attachCredentialsCache(
422438
$http,
423439
$credentials,
424440
$this->config['token_callback']
425441
);
426-
} elseif ($token = $this->getAccessToken()) {
442+
}
443+
444+
if ($token = $this->getAccessToken()) {
427445
$scopes = $this->prepareScopes();
428446
// add refresh subscriber to request a new token
429447
if (isset($token['refresh_token']) && $this->isAccessTokenExpired()) {
430448
$credentials = $this->createUserRefreshCredentials(
431449
$scopes,
432450
$token['refresh_token']
433451
);
434-
$http = $authHandler->attachCredentials(
452+
return $authHandler->attachCredentials(
435453
$http,
436454
$credentials,
437455
$this->config['token_callback']
438456
);
439-
} else {
440-
$http = $authHandler->attachToken($http, $token, (array) $scopes);
441457
}
442-
} elseif ($key = $this->config['developer_key']) {
443-
$http = $authHandler->attachKey($http, $key);
458+
459+
return $authHandler->attachToken($http, $token, (array) $scopes);
460+
}
461+
462+
if ($key = $this->config['developer_key']) {
463+
return $authHandler->attachKey($http, $key);
444464
}
445465

446466
return $http;
@@ -1235,6 +1255,13 @@ private function createApplicationDefaultCredentials()
12351255
$credentials->setSub($sub);
12361256
}
12371257

1258+
if ($credentials instanceof ServiceAccountCredentials && $this->isUsingJwtWithScope()) {
1259+
// tell the credentials to sign scopes into Self-Signed JWTs instead of
1260+
// calling the OAuth2 token endpoint
1261+
// @see https://google.aip.dev/auth/4111#scope-vs-audience
1262+
$credentials->useJwtAccessWithScope();
1263+
}
1264+
12381265
// If we are not using FetchAuthTokenCache yet, create it now
12391266
if (!$credentials instanceof FetchAuthTokenCache) {
12401267
$credentials = new FetchAuthTokenCache(

tests/Google/ClientTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,4 +952,54 @@ public function testClientOptions()
952952
$credentials = $method->invoke($client);
953953
$this->assertEquals('some-quota-project', $credentials->getQuotaProject());
954954
}
955+
956+
public function testCredentialsOptionWithCredentialsLoader()
957+
{
958+
$this->onlyGuzzle6Or7();
959+
960+
$request = null;
961+
$credentials = $this->prophesize('Google\Auth\CredentialsLoader');
962+
$credentials->getCacheKey()
963+
->willReturn('cache-key');
964+
965+
// Ensure the access token provided by our credentials loader is used
966+
$credentials->fetchAuthToken(Argument::any())
967+
->shouldBeCalledOnce()
968+
->willReturn(['access_token' => 'abc']);
969+
970+
$client = new Client(['credentials' => $credentials->reveal()]);
971+
972+
$handler = $this->prophesize('GuzzleHttp\HandlerStack');
973+
$handler->remove('google_auth')
974+
->shouldBeCalledOnce();
975+
$handler->push(Argument::any(), 'google_auth')
976+
->shouldBeCalledOnce()
977+
->will(function($args) use (&$request) {
978+
$middleware = $args[0];
979+
$callable = $middleware(function ($req, $res) use (&$request) {
980+
$request = $req; // test later
981+
});
982+
$callable(new Request('GET', '/fake-uri'), ['auth' => 'google_auth']);
983+
});
984+
985+
$httpClient = $this->prophesize('GuzzleHttp\ClientInterface');
986+
$httpClient->getConfig()
987+
->shouldBeCalledOnce()
988+
->willReturn(['handler' => $handler->reveal()]);
989+
$httpClient->getConfig('base_uri')
990+
->shouldBeCalledOnce();
991+
$httpClient->getConfig('verify')
992+
->shouldBeCalledOnce();
993+
$httpClient->getConfig('proxy')
994+
->shouldBeCalledOnce();
995+
$httpClient->send(Argument::any(), Argument::any())
996+
->shouldNotBeCalled();
997+
998+
$http = $client->authorize($httpClient->reveal());
999+
1000+
$this->assertNotNull($request);
1001+
$authHeader = $request->getHeaderLine('authorization');
1002+
$this->assertNotNull($authHeader);
1003+
$this->assertEquals('Bearer abc', $authHeader);
1004+
}
9551005
}

0 commit comments

Comments
 (0)