PluginProbe
Gmail SMTP / trunk
Gmail SMTP vtrunk
1.2.3.21 1.2.3.20 trunk 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.9 1.2.0 1.2.3.14 1.2.3.15 1.2.3.16 1.2.3.18 1.2.3.5
gmail-smtp / google-api-php-client / vendor / google / auth / src / ApplicationDefaultCredentials.php

ApplicationDefaultCredentials.php in Gmail SMTP trunk, at google-api-php-client/vendor/google/auth/src/ApplicationDefaultCredentials.php

408 lines 15.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * Copyright 2015 Google Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 namespace Google\Auth;
19
20 use DomainException;
21 use Google\Auth\Credentials\AppIdentityCredentials;
22 use Google\Auth\Credentials\GCECredentials;
23 use Google\Auth\Credentials\ImpersonatedServiceAccountCredentials;
24 use Google\Auth\Credentials\ServiceAccountCredentials;
25 use Google\Auth\Credentials\UserRefreshCredentials;
26 use Google\Auth\HttpHandler\HttpClientCache;
27 use Google\Auth\HttpHandler\HttpHandlerFactory;
28 use Google\Auth\Logging\StdOutLogger;
29 use Google\Auth\Middleware\AuthTokenMiddleware;
30 use Google\Auth\Middleware\ProxyAuthTokenMiddleware;
31 use Google\Auth\Subscriber\AuthTokenSubscriber;
32 use GuzzleHttp\Client;
33 use InvalidArgumentException;
34 use Psr\Cache\CacheItemPoolInterface;
35 use Psr\Log\LoggerInterface;
36
37 /**
38 * ApplicationDefaultCredentials obtains the default credentials for
39 * authorizing a request to a Google service.
40 *
41 * Application Default Credentials are described here:
42 * https://developers.google.com/accounts/docs/application-default-credentials
43 *
44 * This class implements the search for the application default credentials as
45 * described in the link.
46 *
47 * It provides three factory methods:
48 * - #get returns the computed credentials object
49 * - #getSubscriber returns an AuthTokenSubscriber built from the credentials object
50 * - #getMiddleware returns an AuthTokenMiddleware built from the credentials object
51 *
52 * This allows it to be used as follows with GuzzleHttp\Client:
53 *
54 * ```
55 * use Google\Auth\ApplicationDefaultCredentials;
56 * use GuzzleHttp\Client;
57 * use GuzzleHttp\HandlerStack;
58 *
59 * $middleware = ApplicationDefaultCredentials::getMiddleware(
60 * 'https://www.googleapis.com/auth/taskqueue'
61 * );
62 * $stack = HandlerStack::create();
63 * $stack->push($middleware);
64 *
65 * $client = new Client([
66 * 'handler' => $stack,
67 * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
68 * 'auth' => 'google_auth' // authorize all requests
69 * ]);
70 *
71 * $res = $client->get('myproject/taskqueues/myqueue');
72 * ```
73 */
74 class ApplicationDefaultCredentials
75 {
76 private const SDK_DEBUG_ENV_VAR = 'GOOGLE_SDK_PHP_LOGGING';
77
78 /**
79 *
80 * Obtains an AuthTokenSubscriber that uses the default FetchAuthTokenInterface
81 * implementation to use in this environment.
82 *
83 * If supplied, $scope is used to in creating the credentials instance if
84 * this does not fallback to the compute engine defaults.
85 *
86 * @deprecated
87 * @param string|string[] $scope the scope of the access request, expressed
88 * either as an Array or as a space-delimited String.
89 * @param callable|null $httpHandler callback which delivers psr7 request
90 * @param array<mixed>|null $cacheConfig configuration for the cache when it's present
91 * @param CacheItemPoolInterface|null $cache A cache implementation, may be
92 * provided if you have one already available for use.
93 * @return AuthTokenSubscriber
94 * @throws DomainException if no implementation can be obtained.
95 */
96 public static function getSubscriber(// @phpstan-ignore-line
97 $scope = null,
98 ?callable $httpHandler = null,
99 ?array $cacheConfig = null,
100 ?CacheItemPoolInterface $cache = null
101 ) {
102 $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache);
103
104 /** @phpstan-ignore-next-line */
105 return new AuthTokenSubscriber($creds, $httpHandler);
106 }
107
108 /**
109 * Obtains an AuthTokenMiddleware that uses the default FetchAuthTokenInterface
110 * implementation to use in this environment.
111 *
112 * If supplied, $scope is used to in creating the credentials instance if
113 * this does not fallback to the compute engine defaults.
114 *
115 * @param string|string[] $scope the scope of the access request, expressed
116 * either as an Array or as a space-delimited String.
117 * @param callable|null $httpHandler callback which delivers psr7 request
118 * @param array<mixed>|null $cacheConfig configuration for the cache when it's present
119 * @param CacheItemPoolInterface|null $cache A cache implementation, may be
120 * provided if you have one already available for use.
121 * @param string $quotaProject specifies a project to bill for access
122 * charges associated with the request.
123 * @return AuthTokenMiddleware
124 * @throws DomainException if no implementation can be obtained.
125 */
126 public static function getMiddleware(
127 $scope = null,
128 ?callable $httpHandler = null,
129 ?array $cacheConfig = null,
130 ?CacheItemPoolInterface $cache = null,
131 $quotaProject = null
132 ) {
133 $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache, $quotaProject);
134
135 return new AuthTokenMiddleware($creds, $httpHandler);
136 }
137
138 /**
139 * Obtains the default FetchAuthTokenInterface implementation to use
140 * in this environment.
141 *
142 * @param string|string[] $scope the scope of the access request, expressed
143 * either as an Array or as a space-delimited String.
144 * @param callable|null $httpHandler callback which delivers psr7 request
145 * @param array<mixed>|null $cacheConfig configuration for the cache when it's present
146 * @param CacheItemPoolInterface|null $cache A cache implementation, may be
147 * provided if you have one already available for use.
148 * @param string|null $quotaProject specifies a project to bill for access
149 * charges associated with the request.
150 * @param string|string[]|null $defaultScope The default scope to use if no
151 * user-defined scopes exist, expressed either as an Array or as a
152 * space-delimited string.
153 * @param string|null $universeDomain Specifies a universe domain to use for the
154 * calling client library.
155 * @param null|false|LoggerInterface $logger A PSR3 compliant LoggerInterface.
156 * @param bool $enableRegionalAccessBoundary Lookup and include the regional access boundary header.
157 *
158 * @return FetchAuthTokenInterface
159 * @throws DomainException if no implementation can be obtained.
160 */
161 public static function getCredentials(
162 $scope = null,
163 ?callable $httpHandler = null,
164 ?array $cacheConfig = null,
165 ?CacheItemPoolInterface $cache = null,
166 $quotaProject = null,
167 $defaultScope = null,
168 ?string $universeDomain = null,
169 null|false|LoggerInterface $logger = null,
170 bool $enableRegionalAccessBoundary = false
171 ) {
172 $creds = null;
173 $jsonKey = CredentialsLoader::fromEnv()
174 ?: CredentialsLoader::fromWellKnownFile();
175 $anyScope = $scope ?: $defaultScope;
176
177 if (!$httpHandler) {
178 if (!($client = HttpClientCache::getHttpClient())) {
179 $client = new Client();
180 HttpClientCache::setHttpClient($client);
181 }
182
183 $httpHandler = HttpHandlerFactory::build($client, $logger);
184 }
185
186 if (is_null($quotaProject)) {
187 // if a quota project isn't specified, try to get one from the env var
188 $quotaProject = CredentialsLoader::quotaProjectFromEnv();
189 }
190
191 if (!is_null($jsonKey)) {
192 if ($quotaProject) {
193 $jsonKey['quota_project_id'] = $quotaProject;
194 }
195 if ($universeDomain) {
196 $jsonKey['universe_domain'] = $universeDomain;
197 }
198 $creds = CredentialsLoader::makeCredentials(
199 $scope,
200 $jsonKey,
201 $defaultScope,
202 $enableRegionalAccessBoundary
203 );
204 } elseif (AppIdentityCredentials::onAppEngine() && !GCECredentials::onAppEngineFlexible()) {
205 $creds = new AppIdentityCredentials($anyScope);
206 } elseif (self::onGce($httpHandler, $cacheConfig, $cache)) {
207 $creds = new GCECredentials(
208 scope: $anyScope,
209 quotaProject: $quotaProject,
210 universeDomain: $universeDomain,
211 enableRegionalAccessBoundary: $enableRegionalAccessBoundary,
212 );
213 $creds->setIsOnGce(true); // save the credentials a trip to the metadata server
214 }
215
216 if (is_null($creds)) {
217 throw new DomainException(self::notFound());
218 }
219 if (!is_null($cache)) {
220 $creds = new FetchAuthTokenCache($creds, $cacheConfig, $cache);
221 }
222 return $creds;
223 }
224
225 /**
226 * Obtains an AuthTokenMiddleware which will fetch an ID token to use in the
227 * Authorization header. The middleware is configured with the default
228 * FetchAuthTokenInterface implementation to use in this environment.
229 *
230 * If supplied, $targetAudience is used to set the "aud" on the resulting
231 * ID token.
232 *
233 * @param string $targetAudience The audience for the ID token.
234 * @param callable|null $httpHandler callback which delivers psr7 request
235 * @param array<mixed>|null $cacheConfig configuration for the cache when it's present
236 * @param CacheItemPoolInterface|null $cache A cache implementation, may be
237 * provided if you have one already available for use.
238 * @return AuthTokenMiddleware
239 * @throws DomainException if no implementation can be obtained.
240 */
241 public static function getIdTokenMiddleware(
242 $targetAudience,
243 ?callable $httpHandler = null,
244 ?array $cacheConfig = null,
245 ?CacheItemPoolInterface $cache = null
246 ) {
247 $creds = self::getIdTokenCredentials($targetAudience, $httpHandler, $cacheConfig, $cache);
248
249 return new AuthTokenMiddleware($creds, $httpHandler);
250 }
251
252 /**
253 * Obtains an ProxyAuthTokenMiddleware which will fetch an ID token to use in the
254 * Authorization header. The middleware is configured with the default
255 * FetchAuthTokenInterface implementation to use in this environment.
256 *
257 * If supplied, $targetAudience is used to set the "aud" on the resulting
258 * ID token.
259 *
260 * @param string $targetAudience The audience for the ID token.
261 * @param callable|null $httpHandler callback which delivers psr7 request
262 * @param array<mixed>|null $cacheConfig configuration for the cache when it's present
263 * @param CacheItemPoolInterface|null $cache A cache implementation, may be
264 * provided if you have one already available for use.
265 * @return ProxyAuthTokenMiddleware
266 * @throws DomainException if no implementation can be obtained.
267 */
268 public static function getProxyIdTokenMiddleware(
269 $targetAudience,
270 ?callable $httpHandler = null,
271 ?array $cacheConfig = null,
272 ?CacheItemPoolInterface $cache = null
273 ) {
274 $creds = self::getIdTokenCredentials($targetAudience, $httpHandler, $cacheConfig, $cache);
275
276 return new ProxyAuthTokenMiddleware($creds, $httpHandler);
277 }
278
279 /**
280 * Obtains the default FetchAuthTokenInterface implementation to use
281 * in this environment, configured with a $targetAudience for fetching an ID
282 * token.
283 *
284 * @param string $targetAudience The audience for the ID token.
285 * @param callable|null $httpHandler callback which delivers psr7 request
286 * @param array<mixed>|null $cacheConfig configuration for the cache when it's present
287 * @param CacheItemPoolInterface|null $cache A cache implementation, may be
288 * provided if you have one already available for use.
289 * @return FetchAuthTokenInterface
290 * @throws DomainException if no implementation can be obtained.
291 * @throws InvalidArgumentException if JSON "type" key is invalid
292 */
293 public static function getIdTokenCredentials(
294 $targetAudience,
295 ?callable $httpHandler = null,
296 ?array $cacheConfig = null,
297 ?CacheItemPoolInterface $cache = null,
298 ) {
299 $creds = null;
300 $jsonKey = CredentialsLoader::fromEnv()
301 ?: CredentialsLoader::fromWellKnownFile();
302
303 if (!$httpHandler) {
304 if (!($client = HttpClientCache::getHttpClient())) {
305 $client = new Client();
306 HttpClientCache::setHttpClient($client);
307 }
308
309 $httpHandler = HttpHandlerFactory::build($client);
310 }
311
312 if (!is_null($jsonKey)) {
313 if (!array_key_exists('type', $jsonKey)) {
314 throw new \InvalidArgumentException('json key is missing the type field');
315 }
316
317 $creds = match ($jsonKey['type']) {
318 'authorized_user' => new UserRefreshCredentials(null, $jsonKey, $targetAudience),
319 'impersonated_service_account' => new ImpersonatedServiceAccountCredentials(
320 scope: null,
321 jsonKey: $jsonKey,
322 targetAudience: $targetAudience,
323 ),
324 'service_account' => new ServiceAccountCredentials(
325 scope: null,
326 jsonKey: $jsonKey,
327 targetAudience: $targetAudience,
328 ),
329 default => throw new InvalidArgumentException('invalid value in the type field')
330 };
331 } elseif (self::onGce($httpHandler, $cacheConfig, $cache)) {
332 $creds = new GCECredentials(targetAudience: $targetAudience);
333 $creds->setIsOnGce(true); // save the credentials a trip to the metadata server
334 }
335
336 if (is_null($creds)) {
337 throw new DomainException(self::notFound());
338 }
339 if (!is_null($cache)) {
340 $creds = new FetchAuthTokenCache($creds, $cacheConfig, $cache);
341 }
342 return $creds;
343 }
344
345 /**
346 * Returns a StdOutLogger instance
347 *
348 * @internal
349 *
350 * @return null|LoggerInterface
351 */
352 public static function getDefaultLogger(): null|LoggerInterface
353 {
354 $loggingFlag = getenv(self::SDK_DEBUG_ENV_VAR);
355
356 // Env var is not set
357 if (empty($loggingFlag)) {
358 return null;
359 }
360
361 $loggingFlag = strtolower($loggingFlag);
362
363 // Env Var is not true
364 if ($loggingFlag !== 'true') {
365 if ($loggingFlag !== 'false') {
366 trigger_error('The ' . self::SDK_DEBUG_ENV_VAR . ' is set, but it is set to another value than false or true. Logging is disabled');
367 }
368
369 return null;
370 }
371
372 return new StdOutLogger();
373 }
374
375 /**
376 * @return string
377 */
378 private static function notFound()
379 {
380 $msg = 'Your default credentials were not found. To set up ';
381 $msg .= 'Application Default Credentials, see ';
382 $msg .= 'https://cloud.google.com/docs/authentication/external/set-up-adc';
383
384 return $msg;
385 }
386
387 /**
388 * @param callable|null $httpHandler
389 * @param array<mixed>|null $cacheConfig
390 * @param CacheItemPoolInterface|null $cache
391 * @return bool
392 */
393 private static function onGce(
394 ?callable $httpHandler = null,
395 ?array $cacheConfig = null,
396 ?CacheItemPoolInterface $cache = null
397 ) {
398 $gceCacheConfig = [];
399 foreach (['lifetime', 'prefix'] as $key) {
400 if (isset($cacheConfig['gce_' . $key])) {
401 $gceCacheConfig[$key] = $cacheConfig['gce_' . $key];
402 }
403 }
404
405 return (new GCECache($gceCacheConfig, $cache))->onGce($httpHandler);
406 }
407 }
408