PluginProbe
Authorizer / 3.6.0
Authorizer v3.6.0
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.6.0, at vendor/google/auth/src/CredentialsLoader.php

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