PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / trunk
Booking for Appointments and Events Calendar – Amelia vtrunk
2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / vendor / google / apiclient / src / AccessToken / Verify.php
ameliabooking / vendor / google / apiclient / src / AccessToken Last commit date
Revoke.php 6 months ago Verify.php 6 months ago
Verify.php
265 lines
1 <?php
2
3 /*
4 * Copyright 2008 Google Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 namespace AmeliaVendor\Google\AccessToken;
20
21 use DateTime;
22 use DomainException;
23 use Exception;
24 use ExpiredException;
25 use AmeliaVendor\Firebase\JWT\ExpiredException as ExpiredExceptionV3;
26 use AmeliaVendor\Firebase\JWT\JWT;
27 use AmeliaVendor\Firebase\JWT\Key;
28 use AmeliaVendor\Firebase\JWT\SignatureInvalidException;
29 use AmeliaVendor\Google\Auth\Cache\MemoryCacheItemPool;
30 use AmeliaVendor\Google\Exception as GoogleException;
31 use AmeliaVendor\GuzzleHttp\Client;
32 use AmeliaVendor\GuzzleHttp\ClientInterface;
33 use InvalidArgumentException;
34 use LogicException;
35 use AmeliaVendor\phpseclib3\Crypt\AES;
36 use AmeliaVendor\phpseclib3\Crypt\PublicKeyLoader;
37 use AmeliaVendor\phpseclib3\Math\BigInteger;
38 use AmeliaVendor\Psr\Cache\CacheItemPoolInterface;
39
40 /**
41 * Wrapper around Google Access Tokens which provides convenience functions
42 *
43 */
44 class Verify
45 {
46 const FEDERATED_SIGNON_CERT_URL = 'https://www.googleapis.com/oauth2/v3/certs';
47 const OAUTH2_ISSUER = 'accounts.google.com';
48 const OAUTH2_ISSUER_HTTPS = 'https://accounts.google.com';
49
50 /**
51 * @var ClientInterface The http client
52 */
53 private $http;
54
55 /**
56 * @var CacheItemPoolInterface cache class
57 */
58 private $cache;
59
60 /**
61 * @var \AmeliaVendor\Firebase\JWT\JWT
62 */
63 public $jwt;
64
65 /**
66 * Instantiates the class, but does not initiate the login flow, leaving it
67 * to the discretion of the caller.
68 */
69 public function __construct(
70 ?ClientInterface $http = null,
71 ?CacheItemPoolInterface $cache = null,
72 $jwt = null
73 ) {
74 if (null === $http) {
75 $http = new Client();
76 }
77
78 if (null === $cache) {
79 $cache = new MemoryCacheItemPool();
80 }
81
82 $this->http = $http;
83 $this->cache = $cache;
84 $this->jwt = $jwt ?: $this->getJwtService();
85 }
86
87 /**
88 * Verifies an id token and returns the authenticated apiLoginTicket.
89 * Throws an exception if the id token is not valid.
90 * The audience parameter can be used to control which id tokens are
91 * accepted. By default, the id token must have been issued to this OAuth2 client.
92 *
93 * @param string $idToken the ID token in JWT format
94 * @param string $audience Optional. The audience to verify against JWt "aud"
95 * @return array|false the token payload, if successful
96 */
97 public function verifyIdToken($idToken, $audience = null)
98 {
99 if (empty($idToken)) {
100 throw new LogicException('id_token cannot be null');
101 }
102
103 // set phpseclib constants if applicable
104 $this->setPhpsecConstants();
105
106 // Check signature
107 $certs = $this->getFederatedSignOnCerts();
108 foreach ($certs as $cert) {
109 try {
110 $args = [$idToken];
111 $publicKey = $this->getPublicKey($cert);
112 if (class_exists(Key::class)) {
113 $args[] = new Key($publicKey, 'RS256');
114 } else {
115 $args[] = $publicKey;
116 $args[] = ['RS256'];
117 }
118 $payload = \call_user_func_array([$this->jwt, 'decode'], $args);
119
120 if (property_exists($payload, 'aud')) {
121 if ($audience && $payload->aud != $audience) {
122 return false;
123 }
124 }
125
126 // support HTTP and HTTPS issuers
127 // @see https://developers.google.com/identity/sign-in/web/backend-auth
128 $issuers = [self::OAUTH2_ISSUER, self::OAUTH2_ISSUER_HTTPS];
129 if (!isset($payload->iss) || !in_array($payload->iss, $issuers)) {
130 return false;
131 }
132
133 return (array) $payload;
134 } catch (ExpiredException $e) { // @phpstan-ignore-line
135 return false;
136 } catch (ExpiredExceptionV3 $e) {
137 return false;
138 } catch (SignatureInvalidException $e) {
139 // continue
140 } catch (DomainException $e) {
141 // continue
142 }
143 }
144
145 return false;
146 }
147
148 private function getCache()
149 {
150 return $this->cache;
151 }
152
153 /**
154 * Retrieve and cache a certificates file.
155 *
156 * @param string $url location
157 * @throws \AmeliaVendor\Google\Exception
158 * @return array certificates
159 */
160 private function retrieveCertsFromLocation($url)
161 {
162 // If we're retrieving a local file, just grab it.
163 if (0 !== strpos($url, 'http')) {
164 if (!$file = file_get_contents($url)) {
165 throw new GoogleException(
166 "Failed to retrieve verification certificates: '" .
167 $url . "'."
168 );
169 }
170
171 return json_decode($file, true);
172 }
173
174 // @phpstan-ignore-next-line
175 $response = $this->http->get($url);
176
177 if ($response->getStatusCode() == 200) {
178 return json_decode((string) $response->getBody(), true);
179 }
180 throw new GoogleException(
181 sprintf(
182 'Failed to retrieve verification certificates: "%s".',
183 $response->getBody()->getContents()
184 ),
185 $response->getStatusCode()
186 );
187 }
188
189 // Gets federated sign-on certificates to use for verifying identity tokens.
190 // Returns certs as array structure, where keys are key ids, and values
191 // are PEM encoded certificates.
192 private function getFederatedSignOnCerts()
193 {
194 $certs = null;
195 if ($cache = $this->getCache()) {
196 $cacheItem = $cache->getItem('federated_signon_certs_v3');
197 $certs = $cacheItem->get();
198 }
199
200
201 if (!$certs) {
202 $certs = $this->retrieveCertsFromLocation(
203 self::FEDERATED_SIGNON_CERT_URL
204 );
205
206 if ($cache) {
207 $cacheItem->expiresAt(new DateTime('+1 hour'));
208 $cacheItem->set($certs);
209 $cache->save($cacheItem);
210 }
211 }
212
213 if (!isset($certs['keys'])) {
214 throw new InvalidArgumentException(
215 'federated sign-on certs expects "keys" to be set'
216 );
217 }
218
219 return $certs['keys'];
220 }
221
222 private function getJwtService()
223 {
224 $jwt = new JWT();
225 if ($jwt::$leeway < 1) {
226 // Ensures JWT leeway is at least 1
227 // @see https://github.com/google/google-api-php-client/issues/827
228 $jwt::$leeway = 1;
229 }
230
231 return $jwt;
232 }
233
234 private function getPublicKey($cert)
235 {
236 $modulus = new BigInteger($this->jwt->urlsafeB64Decode($cert['n']), 256);
237 $exponent = new BigInteger($this->jwt->urlsafeB64Decode($cert['e']), 256);
238 $component = ['n' => $modulus, 'e' => $exponent];
239
240 $loader = PublicKeyLoader::load($component);
241
242 return $loader->toString('PKCS8');
243 }
244
245 /**
246 * phpseclib calls "phpinfo" by default, which requires special
247 * whitelisting in the AppEngine VM environment. This function
248 * sets constants to bypass the need for phpseclib to check phpinfo
249 *
250 * @see phpseclib/Math/BigInteger
251 * @see https://github.com/GoogleCloudPlatform/getting-started-php/issues/85
252 */
253 private function setPhpsecConstants()
254 {
255 if (filter_var(getenv('GAE_VM'), FILTER_VALIDATE_BOOLEAN)) {
256 if (!defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
257 define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
258 }
259 if (!defined('CRYPT_RSA_MODE')) {
260 define('CRYPT_RSA_MODE', AES::ENGINE_OPENSSL);
261 }
262 }
263 }
264 }
265