TheRakeshPurohit /
rtCamp
| 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 | use Firebase\JWT\ExpiredException as ExpiredExceptionV3; |
||
| 20 | use Firebase\JWT\SignatureInvalidException; |
||
| 21 | use GuzzleHttp\Client; |
||
| 22 | use GuzzleHttp\ClientInterface; |
||
| 23 | use Psr\Cache\CacheItemPoolInterface; |
||
| 24 | use Google\Auth\Cache\MemoryCacheItemPool; |
||
| 25 | use Stash\Driver\FileSystem; |
||
|
0 ignored issues
–
show
|
|||
| 26 | use Stash\Pool; |
||
|
0 ignored issues
–
show
This use statement conflicts with another class in this namespace,
Pool. Consider defining an alias.
Let?s assume that you have a directory layout like this: .
|-- OtherDir
| |-- Bar.php
| `-- Foo.php
`-- SomeDir
`-- Foo.php
and let?s assume the following content of // Bar.php
namespace OtherDir;
use SomeDir\Foo; // This now conflicts the class OtherDir\Foo
If both files PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as // Bar.php
namespace OtherDir;
use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
The type
Stash\Pool was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||
| 27 | |||
| 28 | /** |
||
| 29 | * Wrapper around Google Access Tokens which provides convenience functions |
||
| 30 | * |
||
| 31 | */ |
||
| 32 | class Google_AccessToken_Verify |
||
| 33 | { |
||
| 34 | const FEDERATED_SIGNON_CERT_URL = 'https://www.googleapis.com/oauth2/v3/certs'; |
||
| 35 | const OAUTH2_ISSUER = 'accounts.google.com'; |
||
| 36 | const OAUTH2_ISSUER_HTTPS = 'https://accounts.google.com'; |
||
| 37 | |||
| 38 | /** |
||
| 39 | * @var GuzzleHttp\ClientInterface The http client |
||
| 40 | */ |
||
| 41 | private $http; |
||
| 42 | |||
| 43 | /** |
||
| 44 | * @var Psr\Cache\CacheItemPoolInterface cache class |
||
| 45 | */ |
||
| 46 | private $cache; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * Instantiates the class, but does not initiate the login flow, leaving it |
||
| 50 | * to the discretion of the caller. |
||
| 51 | */ |
||
| 52 | public function __construct( |
||
| 53 | ClientInterface $http = null, |
||
| 54 | CacheItemPoolInterface $cache = null, |
||
| 55 | $jwt = null |
||
| 56 | ) { |
||
| 57 | if (null === $http) { |
||
| 58 | $http = new Client(); |
||
| 59 | } |
||
| 60 | |||
| 61 | if (null === $cache) { |
||
| 62 | $cache = new MemoryCacheItemPool; |
||
| 63 | } |
||
| 64 | |||
| 65 | $this->http = $http; |
||
| 66 | $this->cache = $cache; |
||
| 67 | $this->jwt = $jwt ?: $this->getJwtService(); |
||
|
0 ignored issues
–
show
|
|||
| 68 | } |
||
| 69 | |||
| 70 | /** |
||
| 71 | * Verifies an id token and returns the authenticated apiLoginTicket. |
||
| 72 | * Throws an exception if the id token is not valid. |
||
| 73 | * The audience parameter can be used to control which id tokens are |
||
| 74 | * accepted. By default, the id token must have been issued to this OAuth2 client. |
||
| 75 | * |
||
| 76 | * @param $audience |
||
| 77 | * @return array the token payload, if successful |
||
| 78 | */ |
||
| 79 | public function verifyIdToken($idToken, $audience = null) |
||
| 80 | { |
||
| 81 | if (empty($idToken)) { |
||
| 82 | throw new LogicException('id_token cannot be null'); |
||
| 83 | } |
||
| 84 | |||
| 85 | // set phpseclib constants if applicable |
||
| 86 | $this->setPhpsecConstants(); |
||
| 87 | |||
| 88 | // Check signature |
||
| 89 | $certs = $this->getFederatedSignOnCerts(); |
||
| 90 | foreach ($certs as $cert) { |
||
| 91 | $bigIntClass = $this->getBigIntClass(); |
||
| 92 | $rsaClass = $this->getRsaClass(); |
||
| 93 | $modulus = new $bigIntClass($this->jwt->urlsafeB64Decode($cert['n']), 256); |
||
| 94 | $exponent = new $bigIntClass($this->jwt->urlsafeB64Decode($cert['e']), 256); |
||
| 95 | |||
| 96 | $rsa = new $rsaClass(); |
||
| 97 | $rsa->loadKey(array('n' => $modulus, 'e' => $exponent)); |
||
| 98 | |||
| 99 | try { |
||
| 100 | $payload = $this->jwt->decode( |
||
| 101 | $idToken, |
||
| 102 | $rsa->getPublicKey(), |
||
| 103 | array('RS256') |
||
| 104 | ); |
||
| 105 | |||
| 106 | if (property_exists($payload, 'aud')) { |
||
| 107 | if ($audience && $payload->aud != $audience) { |
||
| 108 | return false; |
||
|
0 ignored issues
–
show
|
|||
| 109 | } |
||
| 110 | } |
||
| 111 | |||
| 112 | // support HTTP and HTTPS issuers |
||
| 113 | // @see https://developers.google.com/identity/sign-in/web/backend-auth |
||
| 114 | $issuers = array(self::OAUTH2_ISSUER, self::OAUTH2_ISSUER_HTTPS); |
||
| 115 | if (!isset($payload->iss) || !in_array($payload->iss, $issuers)) { |
||
| 116 | return false; |
||
|
0 ignored issues
–
show
|
|||
| 117 | } |
||
| 118 | |||
| 119 | return (array) $payload; |
||
| 120 | } catch (ExpiredException $e) { |
||
|
0 ignored issues
–
show
The type
ExpiredException was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||
| 121 | return false; |
||
|
0 ignored issues
–
show
|
|||
| 122 | } catch (ExpiredExceptionV3 $e) { |
||
| 123 | return false; |
||
|
0 ignored issues
–
show
|
|||
| 124 | } catch (SignatureInvalidException $e) { |
||
| 125 | // continue |
||
| 126 | } catch (DomainException $e) { |
||
| 127 | // continue |
||
| 128 | } |
||
| 129 | } |
||
| 130 | |||
| 131 | return false; |
||
|
0 ignored issues
–
show
|
|||
| 132 | } |
||
| 133 | |||
| 134 | private function getCache() |
||
| 135 | { |
||
| 136 | return $this->cache; |
||
| 137 | } |
||
| 138 | |||
| 139 | /** |
||
| 140 | * Retrieve and cache a certificates file. |
||
| 141 | * |
||
| 142 | * @param $url string location |
||
| 143 | * @throws Google_Exception |
||
| 144 | * @return array certificates |
||
| 145 | */ |
||
| 146 | private function retrieveCertsFromLocation($url) |
||
| 147 | { |
||
| 148 | // If we're retrieving a local file, just grab it. |
||
| 149 | if (0 !== strpos($url, 'http')) { |
||
| 150 | if (!$file = file_get_contents($url)) { |
||
| 151 | throw new Google_Exception( |
||
| 152 | "Failed to retrieve verification certificates: '" . |
||
| 153 | $url . "'." |
||
| 154 | ); |
||
| 155 | } |
||
| 156 | |||
| 157 | return json_decode($file, true); |
||
| 158 | } |
||
| 159 | |||
| 160 | $response = $this->http->get($url); |
||
| 161 | |||
| 162 | if ($response->getStatusCode() == 200) { |
||
| 163 | return json_decode((string) $response->getBody(), true); |
||
| 164 | } |
||
| 165 | throw new Google_Exception( |
||
| 166 | sprintf( |
||
| 167 | 'Failed to retrieve verification certificates: "%s".', |
||
| 168 | $response->getBody()->getContents() |
||
| 169 | ), |
||
| 170 | $response->getStatusCode() |
||
| 171 | ); |
||
| 172 | } |
||
| 173 | |||
| 174 | // Gets federated sign-on certificates to use for verifying identity tokens. |
||
| 175 | // Returns certs as array structure, where keys are key ids, and values |
||
| 176 | // are PEM encoded certificates. |
||
| 177 | private function getFederatedSignOnCerts() |
||
| 178 | { |
||
| 179 | $certs = null; |
||
| 180 | if ($cache = $this->getCache()) { |
||
| 181 | $cacheItem = $cache->getItem('federated_signon_certs_v3'); |
||
| 182 | $certs = $cacheItem->get(); |
||
| 183 | } |
||
| 184 | |||
| 185 | |||
| 186 | if (!$certs) { |
||
| 187 | $certs = $this->retrieveCertsFromLocation( |
||
| 188 | self::FEDERATED_SIGNON_CERT_URL |
||
| 189 | ); |
||
| 190 | |||
| 191 | if ($cache) { |
||
|
0 ignored issues
–
show
|
|||
| 192 | $cacheItem->expiresAt(new DateTime('+1 hour')); |
||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
| 193 | $cacheItem->set($certs); |
||
| 194 | $cache->save($cacheItem); |
||
| 195 | } |
||
| 196 | } |
||
| 197 | |||
| 198 | if (!isset($certs['keys'])) { |
||
| 199 | throw new InvalidArgumentException( |
||
| 200 | 'federated sign-on certs expects "keys" to be set' |
||
| 201 | ); |
||
| 202 | } |
||
| 203 | |||
| 204 | return $certs['keys']; |
||
| 205 | } |
||
| 206 | |||
| 207 | private function getJwtService() |
||
| 208 | { |
||
| 209 | $jwtClass = 'JWT'; |
||
| 210 | if (class_exists('\Firebase\JWT\JWT')) { |
||
| 211 | $jwtClass = 'Firebase\JWT\JWT'; |
||
| 212 | } |
||
| 213 | |||
| 214 | if (property_exists($jwtClass, 'leeway') && $jwtClass::$leeway < 1) { |
||
| 215 | // Ensures JWT leeway is at least 1 |
||
| 216 | // @see https://github.com/google/google-api-php-client/issues/827 |
||
| 217 | $jwtClass::$leeway = 1; |
||
| 218 | } |
||
| 219 | |||
| 220 | return new $jwtClass; |
||
| 221 | } |
||
| 222 | |||
| 223 | private function getRsaClass() |
||
| 224 | { |
||
| 225 | if (class_exists('phpseclib\Crypt\RSA')) { |
||
| 226 | return 'phpseclib\Crypt\RSA'; |
||
| 227 | } |
||
| 228 | |||
| 229 | return 'Crypt_RSA'; |
||
| 230 | } |
||
| 231 | |||
| 232 | private function getBigIntClass() |
||
| 233 | { |
||
| 234 | if (class_exists('phpseclib\Math\BigInteger')) { |
||
| 235 | return 'phpseclib\Math\BigInteger'; |
||
| 236 | } |
||
| 237 | |||
| 238 | return 'Math_BigInteger'; |
||
| 239 | } |
||
| 240 | |||
| 241 | private function getOpenSslConstant() |
||
| 242 | { |
||
| 243 | if (class_exists('phpseclib\Crypt\RSA')) { |
||
| 244 | return 'phpseclib\Crypt\RSA::MODE_OPENSSL'; |
||
| 245 | } |
||
| 246 | |||
| 247 | if (class_exists('Crypt_RSA')) { |
||
| 248 | return 'CRYPT_RSA_MODE_OPENSSL'; |
||
| 249 | } |
||
| 250 | |||
| 251 | throw new \Exception('Cannot find RSA class'); |
||
| 252 | } |
||
| 253 | |||
| 254 | /** |
||
| 255 | * phpseclib calls "phpinfo" by default, which requires special |
||
| 256 | * whitelisting in the AppEngine VM environment. This function |
||
| 257 | * sets constants to bypass the need for phpseclib to check phpinfo |
||
| 258 | * |
||
| 259 | * @see phpseclib/Math/BigInteger |
||
| 260 | * @see https://github.com/GoogleCloudPlatform/getting-started-php/issues/85 |
||
| 261 | */ |
||
| 262 | private function setPhpsecConstants() |
||
| 263 | { |
||
| 264 | if (filter_var(getenv('GAE_VM'), FILTER_VALIDATE_BOOLEAN)) { |
||
| 265 | if (!defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { |
||
| 266 | define('MATH_BIGINTEGER_OPENSSL_ENABLED', true); |
||
| 267 | } |
||
| 268 | if (!defined('CRYPT_RSA_MODE')) { |
||
| 269 | define('CRYPT_RSA_MODE', constant($this->getOpenSslConstant())); |
||
| 270 | } |
||
| 271 | } |
||
| 272 | } |
||
| 273 | } |
||
| 274 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths