PluginProbe
WP-Stateless – Google Cloud Storage / trunk
WP-Stateless – Google Cloud Storage vtrunk
4.4.3 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.3.0 2.3.1 2.3.2 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 All 62 releases
← All changes | lib/Google/src/Client.php +126 -53 3.2.1trunk View file →
@@ -26,8 +26,10 @@
26 26 use Google\Auth\Credentials\ServiceAccountCredentials;
27 27 use Google\Auth\Credentials\UserRefreshCredentials;
28 28 use Google\Auth\CredentialsLoader;
29 29 use Google\Auth\FetchAuthTokenCache;
30 +use Google\Auth\FetchAuthTokenInterface;
31 +use Google\Auth\GetUniverseDomainInterface;
30 32 use Google\Auth\HttpHandler\HttpHandlerFactory;
31 33 use Google\Auth\OAuth2;
32 34 use Google\AuthHandler\AuthHandlerFactory;
33 35 use Google\Http\REST;
@@ -50,13 +52,13 @@
50 52 * https://github.com/google/google-api-php-client
51 53 */
52 54 class Client
53 55 {
54 - const LIBVER = "2.12.1";
56 + const LIBVER = "2.12.6";
55 57 const USER_AGENT_SUFFIX = "google-api-php-client/";
56 58 const OAUTH2_REVOKE_URI = 'https://oauth2.googleapis.com/revoke';
57 59 const OAUTH2_TOKEN_URI = 'https://oauth2.googleapis.com/token';
58 - const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth';
60 + const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth';
59 61 const API_BASE_PATH = 'https://www.googleapis.com';
60 62
61 63 /**
62 64 * @var ?OAuth2 $auth
@@ -88,9 +90,9 @@
88 90 */
89 91 private $logger;
90 92
91 93 /**
92 - * @var ?CredentialsLoader $credentials
94 + * @var ?FetchAuthTokenInterface $credentials
93 95 */
94 96 private $credentials;
95 97
96 98 /**
@@ -104,84 +106,116 @@
104 106
105 107 /**
106 108 * Construct the Google Client.
107 109 *
108 - * @param array $config
110 + * @param array $config {
111 + * An array of required and optional arguments.
112 + *
113 + * @type string $application_name
114 + * The name of your application
115 + * @type string $base_path
116 + * The base URL for the service. This is only accounted for when calling
117 + * {@see Client::authorize()} directly.
118 + * @type string $client_id
119 + * Your Google Cloud client ID found in https://developers.google.com/console
120 + * @type string $client_secret
121 + * Your Google Cloud client secret found in https://developers.google.com/console
122 + * @type string|array|FetchAuthTokenInterface $credentials
123 + * Can be a path to JSON credentials or an array representing those
124 + * credentials (@see Google\Client::setAuthConfig), or an instance of
125 + * {@see FetchAuthTokenInterface}.
126 + * @type string|array $scopes
127 + * {@see Google\Client::setScopes}
128 + * @type string $quota_project
129 + * Sets X-Goog-User-Project, which specifies a user project to bill
130 + * for access charges associated with the request.
131 + * @type string $redirect_uri
132 + * @type string $state
133 + * @type string $developer_key
134 + * Simple API access key, also from the API console. Ensure you get
135 + * a Server key, and not a Browser key.
136 + * **NOTE:** The universe domain is assumed to be "googleapis.com" unless
137 + * explicitly set. When setting an API ley directly via this option, there
138 + * is no way to verify the universe domain. Be sure to set the
139 + * "universe_domain" option if "googleapis.com" is not intended.
140 + * @type bool $use_application_default_credentials
141 + * For use with Google Cloud Platform
142 + * fetch the ApplicationDefaultCredentials, if applicable
143 + * {@see https://developers.google.com/identity/protocols/application-default-credentials}
144 + * @type string $signing_key
145 + * @type string $signing_algorithm
146 + * @type string $subject
147 + * @type string $hd
148 + * @type string $prompt
149 + * @type string $openid
150 + * @type bool $include_granted_scopes
151 + * @type string $login_hint
152 + * @type string $request_visible_actions
153 + * @type string $access_type
154 + * @type string $approval_prompt
155 + * @type array $retry
156 + * Task Runner retry configuration
157 + * {@see \Google\Task\Runner}
158 + * @type array $retry_map
159 + * @type CacheItemPoolInterface $cache
160 + * Cache class implementing {@see CacheItemPoolInterface}. Defaults
161 + * to {@see MemoryCacheItemPool}.
162 + * @type array $cache_config
163 + * Cache config for downstream auth caching.
164 + * @type callable $token_callback
165 + * Function to be called when an access token is fetched. Follows
166 + * the signature `function (string $cacheKey, string $accessToken)`.
167 + * @type \Firebase\JWT $jwt
168 + * Service class used in {@see Client::verifyIdToken()}. Explicitly
169 + * pass this in to avoid setting {@see \Firebase\JWT::$leeway}
170 + * @type bool $api_format_v2
171 + * Setting api_format_v2 will return more detailed error messages
172 + * from certain APIs.
173 + * @type string $universe_domain
174 + * Setting the universe domain will change the default rootUrl of the service.
175 + * If not set explicitly, the universe domain will be the value provided in the
176 + *. "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable, or "googleapis.com".
177 + * }
109 178 */
110 179 public function __construct(array $config = [])
111 180 {
112 181 $this->config = array_merge([
113 182 'application_name' => '',
114 -
115 - // Don't change these unless you're working against a special development
116 - // or testing environment.
117 183 'base_path' => self::API_BASE_PATH,
118 -
119 - // https://developers.google.com/console
120 184 'client_id' => '',
121 185 'client_secret' => '',
122 -
123 - // Can be a path to JSON credentials or an array representing those
124 - // credentials (@see Google\Client::setAuthConfig), or an instance of
125 - // Google\Auth\CredentialsLoader.
126 186 'credentials' => null,
127 - // @see Google\Client::setScopes
128 187 'scopes' => null,
129 - // Sets X-Goog-User-Project, which specifies a user project to bill
130 - // for access charges associated with the request
131 188 'quota_project' => null,
132 -
133 189 'redirect_uri' => null,
134 190 'state' => null,
135 -
136 - // Simple API access key, also from the API console. Ensure you get
137 - // a Server key, and not a Browser key.
138 191 'developer_key' => '',
139 -
140 - // For use with Google Cloud Platform
141 - // fetch the ApplicationDefaultCredentials, if applicable
142 - // @see https://developers.google.com/identity/protocols/application-default-credentials
143 192 'use_application_default_credentials' => false,
144 193 'signing_key' => null,
145 194 'signing_algorithm' => null,
146 195 'subject' => null,
147 -
148 - // Other OAuth2 parameters.
149 196 'hd' => '',
150 197 'prompt' => '',
151 198 'openid.realm' => '',
152 199 'include_granted_scopes' => null,
200 + 'logger' => null,
153 201 'login_hint' => '',
154 202 'request_visible_actions' => '',
155 203 'access_type' => 'online',
156 204 'approval_prompt' => 'auto',
157 -
158 - // Task Runner retry configuration
159 - // @see Google\Task\Runner
160 205 'retry' => [],
161 206 'retry_map' => null,
162 -
163 - // Cache class implementing Psr\Cache\CacheItemPoolInterface.
164 - // Defaults to Google\Auth\Cache\MemoryCacheItemPool.
165 207 'cache' => null,
166 - // cache config for downstream auth caching
167 208 'cache_config' => [],
168 -
169 - // function to be called when an access token is fetched
170 - // follows the signature function ($cacheKey, $accessToken)
171 209 'token_callback' => null,
172 -
173 - // Service class used in Google\Client::verifyIdToken.
174 - // Explicitly pass this in to avoid setting JWT::$leeway
175 210 'jwt' => null,
176 -
177 - // Setting api_format_v2 will return more detailed error messages
178 - // from certain APIs.
179 - 'api_format_v2' => false
211 + 'api_format_v2' => false,
212 + 'universe_domain' => getenv('GOOGLE_CLOUD_UNIVERSE_DOMAIN')
213 + ?: GetUniverseDomainInterface::DEFAULT_UNIVERSE_DOMAIN,
180 214 ], $config);
181 215
182 216 if (!is_null($this->config['credentials'])) {
183 - if ($this->config['credentials'] instanceof CredentialsLoader) {
217 + if ($this->config['credentials'] instanceof FetchAuthTokenInterface) {
184 218 $this->credentials = $this->config['credentials'];
185 219 } else {
186 220 $this->setAuthConfig($this->config['credentials']);
187 221 }
@@ -209,8 +243,13 @@
209 243 if (!is_null($this->config['cache'])) {
210 244 $this->setCache($this->config['cache']);
211 245 unset($this->config['cache']);
212 246 }
247 +
248 + if (!is_null($this->config['logger'])) {
249 + $this->setLogger($this->config['logger']);
250 + unset($this->config['logger']);
251 + }
213 252 }
214 253
215 254 /**
216 255 * Get a string containing the version of the library.
@@ -239,11 +278,12 @@
239 278 * Attempt to exchange a code for an valid authentication token.
240 279 * Helper wrapped around the OAuth 2.0 implementation.
241 280 *
242 281 * @param string $code code from accounts.google.com
282 + * @param string $codeVerifier the code verifier used for PKCE (if applicable)
243 283 * @return array access token
244 284 */
245 - public function fetchAccessTokenWithAuthCode($code)
285 + public function fetchAccessTokenWithAuthCode($code, $codeVerifier = null)
246 286 {
247 287 if (strlen($code) == 0) {
248 288 throw new InvalidArgumentException("Invalid code");
249 289 }
@@ -250,8 +290,11 @@
250 290
251 291 $auth = $this->getOAuth2Service();
252 292 $auth->setCode($code);
253 293 $auth->setRedirectUri($this->getRedirectUri());
294 + if ($codeVerifier) {
295 + $auth->setCodeVerifier($codeVerifier);
296 + }
254 297
255 298 $httpHandler = HttpHandlerFactory::build($this->getHttpClient());
256 299 $creds = $auth->fetchAuthToken($httpHandler);
257 300 if ($creds && isset($creds['access_token'])) {
@@ -278,9 +321,9 @@
278 321 * Fetches a fresh access token with a given assertion token.
279 322 * @param ClientInterface $authHttp optional.
280 323 * @return array access token
281 324 */
282 - public function fetchAccessTokenWithAssertion(ClientInterface $authHttp = null)
325 + public function fetchAccessTokenWithAssertion(?ClientInterface $authHttp = null)
283 326 {
284 327 if (!$this->isUsingApplicationDefaultCredentials()) {
285 328 throw new DomainException(
286 329 'set the JSON service account credentials using'
@@ -356,11 +399,12 @@
356 399 * Create a URL to obtain user authorization.
357 400 * The authorization endpoint allows the user to first
358 401 * authenticate, and then grant/deny the access request.
359 402 * @param string|array $scope The scope is expressed as an array or list of space-delimited strings.
403 + * @param array $queryParams Querystring params to add to the authorization URL.
360 404 * @return string
361 405 */
362 - public function createAuthUrl($scope = null)
406 + public function createAuthUrl($scope = null, array $queryParams = [])
363 407 {
364 408 if (empty($scope)) {
365 409 $scope = $this->prepareScopes();
366 410 }
@@ -385,12 +429,13 @@
385 429 'include_granted_scopes' => $includeGrantedScopes,
386 430 'login_hint' => $this->config['login_hint'],
387 431 'openid.realm' => $this->config['openid.realm'],
388 432 'prompt' => $this->config['prompt'],
433 + 'redirect_uri' => $this->config['redirect_uri'],
389 434 'response_type' => 'code',
390 435 'scope' => $scope,
391 436 'state' => $this->config['state'],
392 - ]);
437 + ]) + $queryParams;
393 438
394 439 // If the list of scopes contains plus.login, add request_visible_actions
395 440 // to auth URL.
396 441 $rva = $this->config['request_visible_actions'];
@@ -409,20 +454,22 @@
409 454 *
410 455 * @param ClientInterface $http the http client object.
411 456 * @return ClientInterface the http client object
412 457 */
413 - public function authorize(ClientInterface $http = null)
458 + public function authorize(?ClientInterface $http = null)
414 459 {
415 460 $http = $http ?: $this->getHttpClient();
416 461 $authHandler = $this->getAuthHandler();
417 462
418 463 // These conditionals represent the decision tree for authentication
419 - // 1. Check if a Google\Auth\CredentialsLoader instance has been supplied via the "credentials" option
464 + // 1. Check if an instance of Google\Auth\FetchAuthTokenInterface has
465 + // been supplied via the "credentials" option
420 466 // 2. Check for Application Default Credentials
421 467 // 3a. Check for an Access Token
422 468 // 3b. If access token exists but is expired, try to refresh it
423 469 // 4. Check for API Key
424 470 if ($this->credentials) {
471 + $this->checkUniverseDomain($this->credentials);
425 472 return $authHandler->attachCredentials(
426 473 $http,
427 474 $this->credentials,
428 475 $this->config['token_callback']
@@ -430,8 +477,9 @@
430 477 }
431 478
432 479 if ($this->isUsingApplicationDefaultCredentials()) {
433 480 $credentials = $this->createApplicationDefaultCredentials();
481 + $this->checkUniverseDomain($credentials);
434 482 return $authHandler->attachCredentialsCache(
435 483 $http,
436 484 $credentials,
437 485 $this->config['token_callback']
@@ -445,8 +493,9 @@
445 493 $credentials = $this->createUserRefreshCredentials(
446 494 $scopes,
447 495 $token['refresh_token']
448 496 );
497 + $this->checkUniverseDomain($credentials);
449 498 return $authHandler->attachCredentials(
450 499 $http,
451 500 $credentials,
452 501 $this->config['token_callback']
@@ -497,8 +546,13 @@
497 546 * token by calling `$client->getCache()->clear()`. (Use caution in this case,
498 547 * as calling `clear()` will remove all cache items, including any items not
499 548 * related to Google API PHP Client.)
500 549 *
550 + * **NOTE:** The universe domain is assumed to be "googleapis.com" unless
551 + * explicitly set. When setting an access token directly via this method, there
552 + * is no way to verify the universe domain. Be sure to set the "universe_domain"
553 + * option if "googleapis.com" is not intended.
554 + *
501 555 * @param string|array $token
502 556 * @throws InvalidArgumentException
503 557 */
504 558 public function setAccessToken($token)
@@ -875,9 +929,9 @@
875 929 * Helper method to execute deferred HTTP requests.
876 930 *
877 931 * @template T
878 932 * @param RequestInterface $request
879 - * @param class-string<T> $expectedClass
933 + * @param class-string<T>|false|null $expectedClass
880 934 * @throws \Google\Exception
881 935 * @return mixed|T|ResponseInterface
882 936 */
883 937 public function execute(RequestInterface $request, $expectedClass = null)
@@ -990,9 +1044,10 @@
990 1044 }
991 1045
992 1046 $key = isset($config['installed']) ? 'installed' : 'web';
993 1047 if (isset($config['type']) && $config['type'] == 'service_account') {
994 - // application default credentials
1048 + // @TODO(v3): Remove this, as it isn't accurate. ADC applies only to determining
1049 + // credentials based on the user's environment.
995 1050 $this->useApplicationDefaultCredentials();
996 1051
997 1052 // set the information from the config
998 1053 $this->setClientId($config['client_id']);
@@ -1183,9 +1238,8 @@
1183 1238 $guzzleVersion = null;
1184 1239 if (defined('\GuzzleHttp\ClientInterface::MAJOR_VERSION')) {
1185 1240 $guzzleVersion = ClientInterface::MAJOR_VERSION;
1186 1241 } elseif (defined('\GuzzleHttp\ClientInterface::VERSION')) {
1187 - // @phpstan-ignore-next-line
1188 1242 $guzzleVersion = (int)substr(ClientInterface::VERSION, 0, 1);
1189 1243 }
1190 1244
1191 1245 if (5 === $guzzleVersion) {
@@ -1290,6 +1344,25 @@
1290 1344 'refresh_token' => $refreshToken,
1291 1345 ]);
1292 1346
1293 1347 return new UserRefreshCredentials($scope, $creds);
1348 + }
1349 +
1350 + private function checkUniverseDomain($credentials)
1351 + {
1352 + $credentialsUniverse = $credentials instanceof GetUniverseDomainInterface
1353 + ? $credentials->getUniverseDomain()
1354 + : GetUniverseDomainInterface::DEFAULT_UNIVERSE_DOMAIN;
1355 + if ($credentialsUniverse !== $this->getUniverseDomain()) {
1356 + throw new DomainException(sprintf(
1357 + 'The configured universe domain (%s) does not match the credential universe domain (%s)',
1358 + $this->getUniverseDomain(),
1359 + $credentialsUniverse
1360 + ));
1361 + }
1362 + }
1363 +
1364 + public function getUniverseDomain()
1365 + {
1366 + return $this->config['universe_domain'];
1294 1367 }
1295 1368 }