%PDF-1.5 %���� ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY
| Server IP : 14.207.165.8 / Your IP : 216.73.216.26 Web Server : Apache/2.4.18 (Ubuntu) System : Linux 246 4.4.0-210-generic #242-Ubuntu SMP Fri Apr 16 09:57:56 UTC 2021 x86_64 User : root ( 0) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /proc/thread-self/root/var/www/html/water/vendor/yiisoft/yii2-authclient/src/ |
Upload File : |
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\authclient;
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Checker\AlgorithmChecker;
use Jose\Component\Checker\HeaderCheckerManager;
use Jose\Component\KeyManagement\JWKFactory;
use Jose\Component\Signature\JWSLoader;
use Jose\Component\Signature\JWSTokenSupport;
use Jose\Component\Signature\JWSVerifier;
use Jose\Component\Signature\Serializer\CompactSerializer;
use Jose\Component\Signature\Serializer\JWSSerializerManager;
use Yii;
use yii\authclient\signature\HmacSha;
use yii\base\InvalidConfigException;
use yii\caching\Cache;
use yii\di\Instance;
use yii\helpers\Json;
use yii\web\HttpException;
/**
* OpenIdConnect serves as a client for the OpenIdConnect flow.
*
* Application configuration example:
*
* ```php
* 'components' => [
* 'authClientCollection' => [
* 'class' => 'yii\authclient\Collection',
* 'clients' => [
* 'google' => [
* 'class' => 'yii\authclient\OpenIdConnect',
* 'issuerUrl' => 'https://accounts.google.com',
* 'clientId' => 'google_client_id',
* 'clientSecret' => 'google_client_secret',
* 'name' => 'google',
* 'title' => 'Google OpenID Connect',
* ],
* ],
* ]
* // ...
* ]
* ```
*
* This class requires `web-token/jwt-checker`,`web-token/jwt-key-mgmt`, `web-token/jwt-signature`, `web-token/jwt-signature-algorithm-hmac`,
* `web-token/jwt-signature-algorithm-ecdsa` and `web-token/jwt-signature-algorithm-rsa` libraries to be installed for
* JWS verification. This can be done via composer:
*
* ```
* composer require --prefer-dist "web-token/jwt-checker:>=1.0 <3.0" "web-token/jwt-signature:>=1.0 <3.0"
* "web-token/jwt-signature:>=1.0 <3.0" "web-token/jwt-signature-algorithm-hmac:>=1.0 <3.0"
* "web-token/jwt-signature-algorithm-ecdsa:>=1.0 <3.0" "web-token/jwt-signature-algorithm-rsa:>=1.0 <3.0"
* ```
*
* Note: if you are using well-trusted OpenIdConnect provider, you may disable [[validateJws]], making installation of
* `web-token` library redundant, however it is not recommended as it violates the protocol specification.
*
* @see http://openid.net/connect/
* @see OAuth2
*
* @property Cache|null $cache The cache object, `null` - if not enabled. Note that the type of this property
* differs in getter and setter. See [[getCache()]] and [[setCache()]] for details.
* @property array $configParams OpenID provider configuration parameters. This property is read-only.
* @property bool $validateAuthNonce Whether to use and validate auth 'nonce' parameter in authentication
* flow.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.1.3
*/
class OpenIdConnect extends OAuth2
{
/**
* {@inheritdoc}
*/
public $scope = 'openid';
/**
* @var string OpenID Issuer (provider) base URL, e.g. `https://example.com`.
*/
public $issuerUrl;
/**
* @var bool whether to validate/decrypt JWS received with Auth token.
* Note: this functionality requires `web-token/jwt-checker`, `web-token/jwt-key-mgmt`, `web-token/jwt-signature`
* composer package to be installed. You can disable this option in case of usage of trusted OpenIDConnect provider,
* however this violates the protocol rules, so you are doing it on your own risk.
*/
public $validateJws = true;
/**
* @var array JWS algorithms, which are allowed to be used.
* These are used by `web-token` library for JWS validation/decryption.
* Make sure to install `web-token/jwt-signature-algorithm-hmac`, `web-token/jwt-signature-algorithm-ecdsa`
* and `web-token/jwt-signature-algorithm-rsa` packages that support the particular algorithm before adding it here.
*/
public $allowedJwsAlgorithms = [
'HS256', 'HS384', 'HS512',
'ES256', 'ES384', 'ES512',
'RS256', 'RS384', 'RS512',
'PS256', 'PS384', 'PS512'
];
/**
* @var string the prefix for the key used to store [[configParams]] data in cache.
* Actual cache key will be formed addition [[id]] value to it.
* @see cache
*/
public $configParamsCacheKeyPrefix = 'config-params-';
/**
* @var bool|null whether to use and validate auth 'nonce' parameter in authentication flow.
* The option is used for preventing replay attacks.
*/
private $_validateAuthNonce;
/**
* @var array OpenID provider configuration parameters.
*/
private $_configParams;
/**
* @var Cache|string the cache object or the ID of the cache application component that
* is used for caching. This can be one of the following:
*
* - an application component ID (e.g. `cache`)
* - a configuration array
* - a [[\yii\caching\Cache]] object
*
* When this is not set, it means caching is not enabled.
*/
private $_cache = 'cache';
/**
* @var JWSLoader JSON Web Signature
*/
private $_jwsLoader;
/**
* @var JWKSet Key Set
*/
private $_jwkSet;
/**
* @return bool whether to use and validate auth 'nonce' parameter in authentication flow.
*/
public function getValidateAuthNonce()
{
if ($this->_validateAuthNonce === null) {
$this->_validateAuthNonce = $this->validateJws && in_array('nonce', $this->getConfigParam('claims_supported'));
}
return $this->_validateAuthNonce;
}
/**
* @param bool $validateAuthNonce whether to use and validate auth 'nonce' parameter in authentication flow.
*/
public function setValidateAuthNonce($validateAuthNonce)
{
$this->_validateAuthNonce = $validateAuthNonce;
}
/**
* @return Cache|null the cache object, `null` - if not enabled.
*/
public function getCache()
{
if ($this->_cache !== null && !is_object($this->_cache)) {
$this->_cache = Instance::ensure($this->_cache, Cache::className());
}
return $this->_cache;
}
/**
* Sets up a component to be used for caching.
* This can be one of the following:
*
* - an application component ID (e.g. `cache`)
* - a configuration array
* - a [[\yii\caching\Cache]] object
*
* When `null` is passed, it means caching is not enabled.
* @param Cache|array|string|null $cache the cache object or the ID of the cache application component.
*/
public function setCache($cache)
{
$this->_cache = $cache;
}
/**
* @return array OpenID provider configuration parameters.
*/
public function getConfigParams()
{
if ($this->_configParams === null) {
$cache = $this->getCache();
$cacheKey = $this->configParamsCacheKeyPrefix . $this->getId();
if ($cache === null || ($configParams = $cache->get($cacheKey)) === false) {
$configParams = $this->discoverConfig();
}
$this->_configParams = $configParams;
if ($cache !== null) {
$cache->set($cacheKey, $configParams);
}
}
return $this->_configParams;
}
/**
* Returns particular configuration parameter value.
* @param string $name configuration parameter name.
* @return mixed configuration parameter value.
*/
public function getConfigParam($name)
{
$params = $this->getConfigParams();
return $params[$name];
}
/**
* Discovers OpenID Provider configuration parameters.
* @return array OpenID Provider configuration parameters.
* @throws InvalidResponseException on failure.
*/
protected function discoverConfig()
{
$request = $this->createRequest();
$configUrl = rtrim($this->issuerUrl, '/') . '/.well-known/openid-configuration';
$request->setMethod('GET')
->setUrl($configUrl);
$response = $this->sendRequest($request);
return $response;
}
/**
* {@inheritdoc}
*/
public function buildAuthUrl(array $params = [])
{
if ($this->authUrl === null) {
$this->authUrl = $this->getConfigParam('authorization_endpoint');
}
return parent::buildAuthUrl($params);
}
/**
* {@inheritdoc}
*/
public function fetchAccessToken($authCode, array $params = [])
{
if ($this->tokenUrl === null) {
$this->tokenUrl = $this->getConfigParam('token_endpoint');
}
if (!isset($params['nonce']) && $this->getValidateAuthNonce()) {
$nonce = $this->generateAuthNonce();
$this->setState('authNonce', $nonce);
$params['nonce'] = $nonce;
}
return parent::fetchAccessToken($authCode, $params);
}
/**
* {@inheritdoc}
*/
public function refreshAccessToken(OAuthToken $token)
{
if ($this->tokenUrl === null) {
$this->tokenUrl = $this->getConfigParam('token_endpoint');
}
return parent::refreshAccessToken($token);
}
/**
* {@inheritdoc}
*/
protected function initUserAttributes()
{
return $this->api($this->getConfigParam('userinfo_endpoint'), 'GET');
}
/**
* {@inheritdoc}
*/
public function applyAccessTokenToRequest($request, $accessToken)
{
// OpenID Connect requires bearer token auth for the user info endpoint
$request->getHeaders()->set('Authorization', 'Bearer ' . $accessToken->getToken());
}
/**
* {@inheritdoc}
*/
protected function applyClientCredentialsToRequest($request)
{
$supportedAuthMethods = $this->getConfigParam('token_endpoint_auth_methods_supported');
if (in_array('client_secret_basic', $supportedAuthMethods)) {
$request->addHeaders([
'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
]);
} elseif (in_array('client_secret_post', $supportedAuthMethods)) {
$request->addData([
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
]);
} elseif (in_array('client_secret_jwt', $supportedAuthMethods)) {
$header = [
'typ' => 'JWT',
'alg' => 'HS256',
];
$payload = [
'iss' => $this->clientId,
'sub' => $this->clientId,
'aud' => $this->tokenUrl,
'jti' => $this->generateAuthNonce(),
'iat' => time(),
'exp' => time() + 3600,
];
$signatureBaseString = base64_encode(Json::encode($header)) . '.' . base64_encode(Json::encode($payload));
$signatureMethod = new HmacSha(['algorithm' => 'sha256']);
$signature = $signatureMethod->generateSignature($signatureBaseString, $this->clientSecret);
$assertion = $signatureBaseString . '.' . $signature;
$request->addData([
'assertion' => $assertion,
]);
} else {
throw new InvalidConfigException('Unable to authenticate request: none of following auth methods is suported: ' . implode(', ', $supportedAuthMethods));
}
}
/**
* {@inheritdoc}
*/
protected function createToken(array $tokenConfig = [])
{
if ($this->validateJws) {
$jwsData = $this->loadJws($tokenConfig['params']['id_token']);
$this->validateClaims($jwsData);
$tokenConfig['params'] = array_merge($tokenConfig['params'], $jwsData);
if ($this->getValidateAuthNonce()) {
$authNonce = $this->getState('authNonce');
if (!isset($jwsData['nonce']) || empty($authNonce) || strcmp($jwsData['nonce'], $authNonce) !== 0) {
throw new HttpException(400, 'Invalid auth nonce');
} else {
$this->removeState('authNonce');
}
}
}
return parent::createToken($tokenConfig);
}
/**
* Return JwkSet, returning related data.
* @return JWKSet object represents a key set.
* @throws InvalidResponseException on failure.
*/
protected function getJwkSet()
{
if ($this->_jwkSet === null) {
$cache = $this->getCache();
$cacheKey = $this->configParamsCacheKeyPrefix . '_jwkSet';
if ($cache === null || ($jwkSet = $cache->get($cacheKey)) === false) {
$request = $this->createRequest()
->setMethod('GET')
->setUrl($this->getConfigParam('jwks_uri'));
$response = $this->sendRequest($request);
$jwkSet = JWKFactory::createFromValues($response);
}
$this->_jwkSet = $jwkSet;
if ($cache !== null) {
$cache->set($cacheKey, $jwkSet);
}
}
return $this->_jwkSet;
}
/**
* Return JWSLoader that validate the JWS token.
* @return JWSLoader to do token validation.
* @throws InvalidConfigException on invalid algorithm provide in configuration.
*/
protected function getJwsLoader()
{
if ($this->_jwsLoader === null) {
$algorithms = [];
foreach ($this->allowedJwsAlgorithms as $algorithm)
{
$class = '\Jose\Component\Signature\Algorithm\\' . $algorithm;
if (!class_exists($class))
{
throw new InvalidConfigException("Alogrithm class $class doesn't exist");
}
$algorithms[] = new $class();
}
$this->_jwsLoader = new JWSLoader(
new JWSSerializerManager([ new CompactSerializer() ]),
new JWSVerifier(new AlgorithmManager($algorithms)),
new HeaderCheckerManager(
[ new AlgorithmChecker($this->allowedJwsAlgorithms) ],
[ new JWSTokenSupport() ]
)
);
}
return $this->_jwsLoader;
}
/**
* Decrypts/validates JWS, returning related data.
* @param string $jws raw JWS input.
* @return array JWS underlying data.
* @throws HttpException on invalid JWS signature.
*/
protected function loadJws($jws)
{
try {
$jwsLoader = $this->getJwsLoader();
$signature = null;
$jwsVerified = $jwsLoader->loadAndVerifyWithKeySet($jws, $this->getJwkSet(), $signature);
return Json::decode($jwsVerified->getPayload());
} catch (\Exception $e) {
$message = YII_DEBUG ? 'Unable to verify JWS: ' . $e->getMessage() : 'Invalid JWS';
throw new HttpException(400, $message, $e->getCode(), $e);
}
}
/**
* Validates the claims data received from OpenID provider.
* @param array $claims claims data.
* @throws HttpException on invalid claims.
* @since 2.2.3
*/
protected function validateClaims(array $claims)
{
if (!isset($claims['iss']) || (strcmp(rtrim($claims['iss'], '/'), rtrim($this->issuerUrl, '/')) !== 0)) {
throw new HttpException(400, 'Invalid "iss"');
}
if (!isset($claims['aud']) || (strcmp($claims['aud'], $this->clientId) !== 0)) {
throw new HttpException(400, 'Invalid "aud"');
}
}
/**
* Generates the auth nonce value.
* @return string auth nonce value.
*/
protected function generateAuthNonce()
{
return Yii::$app->security->generateRandomString();
}
}