* @link http://github.com/Nodge/yii2-eauth/ * @license http://www.opensource.org/licenses/bsd-license.php */ namespace common\components\nodge\eauth\src; use Yii; use yii\base\Object; use yii\helpers\ArrayHelper; use yii\helpers\Url; /** * The EAuth class provides simple authentication via OpenID and OAuth providers. * * @package application.extensions.eauth */ class EAuth extends Object { /** * @var array Authorization services and their settings. */ protected $services = []; /** * @var boolean Whether to use popup window for the authorization dialog. */ protected $popup = true; /** * @var string|bool Cache component name to use. False to disable cache. */ public $cache = null; /** * @var integer the number of seconds in which the cached value will expire. 0 means never expire. */ public $cacheExpire = 0; /** * @var string popup redirect view with custom js code */ protected $redirectWidget = '\\nodge\\eauth\\RedirectWidget'; /** * @var array TokenStorage class. */ protected $tokenStorage = [ 'class' => 'nodge\eauth\oauth\SessionTokenStorage', ]; /** * @var array HttpClient class. */ protected $httpClient = [ 'class' => 'nodge\eauth\oauth\HttpClient', // 'useStreamsFallback' => false, ]; /** * Initialize the component. */ public function init() { parent::init(); // set default cache on production environments if (!isset($this->cache) && YII_ENV_PROD) { $this->cache = 'cache'; } } /** * @param array $services */ public function setServices($services) { $this->services = $services; } /** * Returns services settings declared in the authorization classes. * For perfomance reasons it uses cache to store settings array. * * @return \stdClass[] services settings. */ public function getServices() { $services = false; if (!empty($this->cache) && Yii::$app->has($this->cache)) { /** @var $cache \yii\caching\Cache */ $cache = Yii::$app->get($this->cache); $services = $cache->get('EAuth.services'); } if (false === $services || !is_array($services)) { $services = []; foreach ($this->services as $service => $options) { /** @var $class ServiceBase */ $class = $this->getIdentity($service); $services[$service] = (object)[ 'id' => $class->getServiceName(), 'title' => $class->getServiceTitle(), 'type' => $class->getServiceType(), 'jsArguments' => $class->getJsArguments(), ]; } if (isset($cache)) { $cache->set('EAuth.services', $services, $this->cacheExpire); } } return $services; } /** * @param bool $usePopup */ public function setPopup($usePopup) { $this->popup = $usePopup; } /** * @return bool */ public function getPopup() { return $this->popup; } /** * @param string|bool $cache */ public function setCache($cache) { $this->cache = $cache; } /** * @return string|bool */ public function getCache() { return $this->cache; } /** * @param int $cacheExpire */ public function setCacheExpire($cacheExpire) { $this->cacheExpire = $cacheExpire; } /** * @return int */ public function getCacheExpire() { return $this->cacheExpire; } /** * @param string $redirectWidget */ public function setRedirectWidget($redirectWidget) { $this->redirectWidget = $redirectWidget; } /** * @return string */ public function getRedirectWidget() { return $this->redirectWidget; } /** * @param array $config */ public function setTokenStorage(array $config) { $this->tokenStorage = ArrayHelper::merge($this->tokenStorage, $config); } /** * @return array */ public function getTokenStorage() { return $this->tokenStorage; } /** * @param array $config */ public function setHttpClient(array $config) { $this->httpClient = ArrayHelper::merge($this->httpClient, $config); } /** * @return array */ public function getHttpClient() { return $this->httpClient; } /** * Returns the settings of the service. * * @param string $service the service name. * @return \stdClass the service settings. * @throws ErrorException */ protected function getService($service) { $service = strtolower($service); $services = $this->getServices(); if (!isset($services[$service])) { throw new ErrorException(Yii::t('eauth', 'Undefined service name: {service}.', ['service' => $service]), 500); } return $services[$service]; } /** * Returns the type of the service. * * @param string $service the service name. * @return string the service type. */ public function getServiceType($service) { $service = $this->getService($service); return $service->type; } /** * Returns the service identity class. * * @param string $service the service name. * @return IAuthService the identity class. * @throws ErrorException */ public function getIdentity($service) { $service = strtolower($service); if (!isset($this->services[$service])) { throw new ErrorException(Yii::t('eauth', 'Undefined service name: {service}.', ['service' => $service]), 500); } $service = $this->services[$service]; $service['component'] = $this; /** @var $identity IAuthService */ $identity = Yii::createObject($service); return $identity; } /** * Redirects to url. If the authorization dialog opened in the popup window, * it will be closed instead of redirect. Set $jsRedirect=true if you want * to redirect anyway. * * @param mixed $url url to redirect. Can be route or normal url. See {@link CHtml::normalizeUrl}. * @param boolean $jsRedirect whether to use redirect while popup window is used. Defaults to true. * @param array $params */ public function redirect($url, $jsRedirect = true, $params = []) { /** @var RedirectWidget $widget */ $widget = Yii::createObject([ 'class' => $this->redirectWidget, 'url' => Url::to($url), 'redirect' => $jsRedirect, 'params' => $params ]); ob_start(); $widget->run(); $output = ob_get_clean(); $response = Yii::$app->getResponse(); $response->content = $output; $response->send(); exit(); } /** * Serialize the identity class. * * @param ServiceBase $identity the class instance. * @return string serialized value. */ public function toString($identity) { return serialize($identity); } /** * Serialize the identity class. * * @param string $identity serialized value. * @return ServiceBase the class instance. */ public function fromString($identity) { return unserialize($identity); } }