PluginProbe
Authorizer / 3.9.1
Authorizer v3.9.1
3.15.3 3.15.2 3.15.1 3.15.0 3.14.3 3.14.4 3.14.2 3.14.1 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.9.0 2.9.1 2.9.10 2.9.11 2.9.12 2.9.13 2.9.2 2.9.3 2.9.6 All 126 releases
authorizer / vendor / google / auth / src / CredentialsLoader.php

CredentialsLoader.php in Authorizer 3.9.1, at vendor/google/auth/src/CredentialsLoader.php

294 lines 9.7 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 Google\Auth\Credentials\ImpersonatedServiceAccountCredentials;
21 use Google\Auth\Credentials\InsecureCredentials;
22 use Google\Auth\Credentials\ServiceAccountCredentials;
23 use Google\Auth\Credentials\UserRefreshCredentials;
24 use RuntimeException;
25 use UnexpectedValueException;
26
27 /**
28 * CredentialsLoader contains the behaviour used to locate and find default
29 * credentials files on the file system.
30 */
31 abstract class CredentialsLoader implements
32 FetchAuthTokenInterface,
33 UpdateMetadataInterface
34 {
35 const TOKEN_CREDENTIAL_URI = 'https://oauth2.googleapis.com/token';
36 const ENV_VAR = 'GOOGLE_APPLICATION_CREDENTIALS';
37 const WELL_KNOWN_PATH = 'gcloud/application_default_credentials.json';
38 const NON_WINDOWS_WELL_KNOWN_PATH_BASE = '.config';
39 const MTLS_WELL_KNOWN_PATH = '.secureConnect/context_aware_metadata.json';
40 const MTLS_CERT_ENV_VAR = 'GOOGLE_API_USE_CLIENT_CERTIFICATE';
41
42 /**
43 * @param string $cause
44 * @return string
45 */
46 private static function unableToReadEnv($cause)
47 {
48 $msg = 'Unable to read the credential file specified by ';
49 $msg .= ' GOOGLE_APPLICATION_CREDENTIALS: ';
50 $msg .= $cause;
51
52 return $msg;
53 }
54
55 /**
56 * @return bool
57 */
58 private static function isOnWindows()
59 {
60 return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
61 }
62
63 /**
64 * Load a JSON key from the path specified in the environment.
65 *
66 * Load a JSON key from the path specified in the environment
67 * variable GOOGLE_APPLICATION_CREDENTIALS. Return null if
68 * GOOGLE_APPLICATION_CREDENTIALS is not specified.
69 *
70 * @return array<mixed>|null JSON key | null
71 */
72 public static function fromEnv()
73 {
74 $path = getenv(self::ENV_VAR);
75 if (empty($path)) {
76 return null;
77 }
78 if (!file_exists($path)) {
79 $cause = 'file ' . $path . ' does not exist';
80 throw new \DomainException(self::unableToReadEnv($cause));
81 }
82 $jsonKey = file_get_contents($path);
83 return json_decode((string) $jsonKey, true);
84 }
85
86 /**
87 * Load a JSON key from a well known path.
88 *
89 * The well known path is OS dependent:
90 *
91 * * windows: %APPDATA%/gcloud/application_default_credentials.json
92 * * others: $HOME/.config/gcloud/application_default_credentials.json
93 *
94 * If the file does not exist, this returns null.
95 *
96 * @return array<mixed>|null JSON key | null
97 */
98 public static function fromWellKnownFile()
99 {
100 $rootEnv = self::isOnWindows() ? 'APPDATA' : 'HOME';
101 $path = [getenv($rootEnv)];
102 if (!self::isOnWindows()) {
103 $path[] = self::NON_WINDOWS_WELL_KNOWN_PATH_BASE;
104 }
105 $path[] = self::WELL_KNOWN_PATH;
106 $path = implode(DIRECTORY_SEPARATOR, $path);
107 if (!file_exists($path)) {
108 return null;
109 }
110 $jsonKey = file_get_contents($path);
111 return json_decode((string) $jsonKey, true);
112 }
113
114 /**
115 * Create a new Credentials instance.
116 *
117 * @param string|string[] $scope the scope of the access request, expressed
118 * either as an Array or as a space-delimited String.
119 * @param array<mixed> $jsonKey the JSON credentials.
120 * @param string|string[] $defaultScope The default scope to use if no
121 * user-defined scopes exist, expressed either as an Array or as a
122 * space-delimited string.
123 *
124 * @return ServiceAccountCredentials|UserRefreshCredentials|ImpersonatedServiceAccountCredentials
125 */
126 public static function makeCredentials(
127 $scope,
128 array $jsonKey,
129 $defaultScope = null
130 ) {
131 if (!array_key_exists('type', $jsonKey)) {
132 throw new \InvalidArgumentException('json key is missing the type field');
133 }
134
135 if ($jsonKey['type'] == 'service_account') {
136 // Do not pass $defaultScope to ServiceAccountCredentials
137 return new ServiceAccountCredentials($scope, $jsonKey);
138 }
139
140 if ($jsonKey['type'] == 'authorized_user') {
141 $anyScope = $scope ?: $defaultScope;
142 return new UserRefreshCredentials($anyScope, $jsonKey);
143 }
144
145 if ($jsonKey['type'] == 'impersonated_service_account') {
146 $anyScope = $scope ?: $defaultScope;
147 return new ImpersonatedServiceAccountCredentials($anyScope, $jsonKey);
148 }
149
150 throw new \InvalidArgumentException('invalid value in the type field');
151 }
152
153 /**
154 * Create an authorized HTTP Client from an instance of FetchAuthTokenInterface.
155 *
156 * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
157 * @param array<mixed> $httpClientOptions (optional) Array of request options to apply.
158 * @param callable $httpHandler (optional) http client to fetch the token.
159 * @param callable $tokenCallback (optional) function to be called when a new token is fetched.
160 * @return \GuzzleHttp\Client
161 */
162 public static function makeHttpClient(
163 FetchAuthTokenInterface $fetcher,
164 array $httpClientOptions = [],
165 callable $httpHandler = null,
166 callable $tokenCallback = null
167 ) {
168 $middleware = new Middleware\AuthTokenMiddleware(
169 $fetcher,
170 $httpHandler,
171 $tokenCallback
172 );
173 $stack = \GuzzleHttp\HandlerStack::create();
174 $stack->push($middleware);
175
176 return new \GuzzleHttp\Client([
177 'handler' => $stack,
178 'auth' => 'google_auth',
179 ] + $httpClientOptions);
180 }
181
182 /**
183 * Create a new instance of InsecureCredentials.
184 *
185 * @return InsecureCredentials
186 */
187 public static function makeInsecureCredentials()
188 {
189 return new InsecureCredentials();
190 }
191
192 /**
193 * export a callback function which updates runtime metadata.
194 *
195 * @return callable updateMetadata function
196 * @deprecated
197 */
198 public function getUpdateMetadataFunc()
199 {
200 return [$this, 'updateMetadata'];
201 }
202
203 /**
204 * Updates metadata with the authorization token.
205 *
206 * @param array<mixed> $metadata metadata hashmap
207 * @param string $authUri optional auth uri
208 * @param callable $httpHandler callback which delivers psr7 request
209 * @return array<mixed> updated metadata hashmap
210 */
211 public function updateMetadata(
212 $metadata,
213 $authUri = null,
214 callable $httpHandler = null
215 ) {
216 if (isset($metadata[self::AUTH_METADATA_KEY])) {
217 // Auth metadata has already been set
218 return $metadata;
219 }
220 $result = $this->fetchAuthToken($httpHandler);
221 $metadata_copy = $metadata;
222 if (isset($result['access_token'])) {
223 $metadata_copy[self::AUTH_METADATA_KEY] = ['Bearer ' . $result['access_token']];
224 } elseif (isset($result['id_token'])) {
225 $metadata_copy[self::AUTH_METADATA_KEY] = ['Bearer ' . $result['id_token']];
226 }
227 return $metadata_copy;
228 }
229
230 /**
231 * Gets a callable which returns the default device certification.
232 *
233 * @throws UnexpectedValueException
234 * @return callable|null
235 */
236 public static function getDefaultClientCertSource()
237 {
238 if (!$clientCertSourceJson = self::loadDefaultClientCertSourceFile()) {
239 return null;
240 }
241 $clientCertSourceCmd = $clientCertSourceJson['cert_provider_command'];
242
243 return function () use ($clientCertSourceCmd) {
244 $cmd = array_map('escapeshellarg', $clientCertSourceCmd);
245 exec(implode(' ', $cmd), $output, $returnVar);
246
247 if (0 === $returnVar) {
248 return implode(PHP_EOL, $output);
249 }
250 throw new RuntimeException(
251 '"cert_provider_command" failed with a nonzero exit code'
252 );
253 };
254 }
255
256 /**
257 * Determines whether or not the default device certificate should be loaded.
258 *
259 * @return bool
260 */
261 public static function shouldLoadClientCertSource()
262 {
263 return filter_var(getenv(self::MTLS_CERT_ENV_VAR), FILTER_VALIDATE_BOOLEAN);
264 }
265
266 /**
267 * @return array{cert_provider_command:string[]}|null
268 */
269 private static function loadDefaultClientCertSourceFile()
270 {
271 $rootEnv = self::isOnWindows() ? 'APPDATA' : 'HOME';
272 $path = sprintf('%s/%s', getenv($rootEnv), self::MTLS_WELL_KNOWN_PATH);
273 if (!file_exists($path)) {
274 return null;
275 }
276 $jsonKey = file_get_contents($path);
277 $clientCertSourceJson = json_decode((string) $jsonKey, true);
278 if (!$clientCertSourceJson) {
279 throw new UnexpectedValueException('Invalid client cert source JSON');
280 }
281 if (!isset($clientCertSourceJson['cert_provider_command'])) {
282 throw new UnexpectedValueException(
283 'cert source requires "cert_provider_command"'
284 );
285 }
286 if (!is_array($clientCertSourceJson['cert_provider_command'])) {
287 throw new UnexpectedValueException(
288 'cert source expects "cert_provider_command" to be an array'
289 );
290 }
291 return $clientCertSourceJson;
292 }
293 }
294