PageRenderTime 43ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/yiisoft/yii2-authclient/AuthAction.php

https://gitlab.com/itlboy/yii2-starter-installed
PHP | 367 lines | 181 code | 29 blank | 157 comment | 28 complexity | 6ef9d5865b80a0cff4751c91e59c01be MD5 | raw file
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\authclient;
  8. use yii\base\Action;
  9. use yii\base\Exception;
  10. use yii\base\InvalidConfigException;
  11. use yii\base\NotSupportedException;
  12. use yii\helpers\Url;
  13. use yii\web\Response;
  14. use yii\web\HttpException;
  15. use yii\web\NotFoundHttpException;
  16. use Yii;
  17. /**
  18. * AuthAction performs authentication via different auth clients.
  19. * It supports [[OpenId]], [[OAuth1]] and [[OAuth2]] client types.
  20. *
  21. * Usage:
  22. *
  23. * ```php
  24. * class SiteController extends Controller
  25. * {
  26. * public function actions()
  27. * {
  28. * return [
  29. * 'auth' => [
  30. * 'class' => 'yii\authclient\AuthAction',
  31. * 'successCallback' => [$this, 'successCallback'],
  32. * ],
  33. * ]
  34. * }
  35. *
  36. * public function successCallback($client)
  37. * {
  38. * $attributes = $client->getUserAttributes();
  39. * // user login or signup comes here
  40. * }
  41. * }
  42. * ```
  43. *
  44. * Usually authentication via external services is performed inside the popup window.
  45. * This action handles the redirection and closing of popup window correctly.
  46. *
  47. * @see Collection
  48. * @see \yii\authclient\widgets\AuthChoice
  49. *
  50. * @property string $cancelUrl Cancel URL.
  51. * @property string $successUrl Successful URL.
  52. *
  53. * @author Paul Klimov <klimov.paul@gmail.com>
  54. * @since 2.0
  55. */
  56. class AuthAction extends Action
  57. {
  58. /**
  59. * @var string name of the auth client collection application component.
  60. * It should point to [[Collection]] instance.
  61. */
  62. public $clientCollection = 'authClientCollection';
  63. /**
  64. * @var string name of the GET param, which is used to passed auth client id to this action.
  65. * Note: watch for the naming, make sure you do not choose name used in some auth protocol.
  66. */
  67. public $clientIdGetParamName = 'authclient';
  68. /**
  69. * @var callable PHP callback, which should be triggered in case of successful authentication.
  70. * This callback should accept [[ClientInterface]] instance as an argument.
  71. * For example:
  72. *
  73. * ```php
  74. * public function onAuthSuccess($client)
  75. * {
  76. * $attributes = $client->getUserAttributes();
  77. * // user login or signup comes here
  78. * }
  79. * ```
  80. *
  81. * If this callback returns [[Response]] instance, it will be used as action response,
  82. * otherwise redirection to [[successUrl]] will be performed.
  83. *
  84. */
  85. public $successCallback;
  86. /**
  87. * @var string name or alias of the view file, which should be rendered in order to perform redirection.
  88. * If not set - default one will be used.
  89. */
  90. public $redirectView;
  91. /**
  92. * @var string the redirect url after successful authorization.
  93. */
  94. private $_successUrl = '';
  95. /**
  96. * @var string the redirect url after unsuccessful authorization (e.g. user canceled).
  97. */
  98. private $_cancelUrl = '';
  99. /**
  100. * @param string $url successful URL.
  101. */
  102. public function setSuccessUrl($url)
  103. {
  104. $this->_successUrl = $url;
  105. }
  106. /**
  107. * @return string successful URL.
  108. */
  109. public function getSuccessUrl()
  110. {
  111. if (empty($this->_successUrl)) {
  112. $this->_successUrl = $this->defaultSuccessUrl();
  113. }
  114. return $this->_successUrl;
  115. }
  116. /**
  117. * @param string $url cancel URL.
  118. */
  119. public function setCancelUrl($url)
  120. {
  121. $this->_cancelUrl = $url;
  122. }
  123. /**
  124. * @return string cancel URL.
  125. */
  126. public function getCancelUrl()
  127. {
  128. if (empty($this->_cancelUrl)) {
  129. $this->_cancelUrl = $this->defaultCancelUrl();
  130. }
  131. return $this->_cancelUrl;
  132. }
  133. /**
  134. * Creates default [[successUrl]] value.
  135. * @return string success URL value.
  136. */
  137. protected function defaultSuccessUrl()
  138. {
  139. return Yii::$app->getUser()->getReturnUrl();
  140. }
  141. /**
  142. * Creates default [[cancelUrl]] value.
  143. * @return string cancel URL value.
  144. */
  145. protected function defaultCancelUrl()
  146. {
  147. return Url::to(Yii::$app->getUser()->loginUrl);
  148. }
  149. /**
  150. * Runs the action.
  151. */
  152. public function run()
  153. {
  154. if (!empty($_GET[$this->clientIdGetParamName])) {
  155. $clientId = $_GET[$this->clientIdGetParamName];
  156. /* @var $collection \yii\authclient\Collection */
  157. $collection = Yii::$app->get($this->clientCollection);
  158. if (!$collection->hasClient($clientId)) {
  159. throw new NotFoundHttpException("Unknown auth client '{$clientId}'");
  160. }
  161. $client = $collection->getClient($clientId);
  162. return $this->auth($client);
  163. }
  164. throw new NotFoundHttpException();
  165. }
  166. /**
  167. * Perform authentication for the given client.
  168. * @param mixed $client auth client instance.
  169. * @return Response response instance.
  170. * @throws \yii\base\NotSupportedException on invalid client.
  171. */
  172. protected function auth($client)
  173. {
  174. if ($client instanceof OAuth2) {
  175. return $this->authOAuth2($client);
  176. } elseif ($client instanceof OAuth1) {
  177. return $this->authOAuth1($client);
  178. } elseif ($client instanceof OpenId) {
  179. return $this->authOpenId($client);
  180. }
  181. throw new NotSupportedException('Provider "' . get_class($client) . '" is not supported.');
  182. }
  183. /**
  184. * This method is invoked in case of successful authentication via auth client.
  185. * @param ClientInterface $client auth client instance.
  186. * @throws InvalidConfigException on invalid success callback.
  187. * @return Response response instance.
  188. */
  189. protected function authSuccess($client)
  190. {
  191. if (!is_callable($this->successCallback)) {
  192. throw new InvalidConfigException('"' . get_class($this) . '::successCallback" should be a valid callback.');
  193. }
  194. $response = call_user_func($this->successCallback, $client);
  195. if ($response instanceof Response) {
  196. return $response;
  197. }
  198. return $this->redirectSuccess();
  199. }
  200. /**
  201. * Redirect to the given URL or simply close the popup window.
  202. * @param mixed $url URL to redirect, could be a string or array config to generate a valid URL.
  203. * @param boolean $enforceRedirect indicates if redirect should be performed even in case of popup window.
  204. * @return \yii\web\Response response instance.
  205. */
  206. public function redirect($url, $enforceRedirect = true)
  207. {
  208. $viewFile = $this->redirectView;
  209. if ($viewFile === null) {
  210. $viewFile = __DIR__ . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . 'redirect.php';
  211. } else {
  212. $viewFile = Yii::getAlias($viewFile);
  213. }
  214. $viewData = [
  215. 'url' => $url,
  216. 'enforceRedirect' => $enforceRedirect,
  217. ];
  218. $response = Yii::$app->getResponse();
  219. $response->content = Yii::$app->getView()->renderFile($viewFile, $viewData);
  220. return $response;
  221. }
  222. /**
  223. * Redirect to the URL. If URL is null, [[successUrl]] will be used.
  224. * @param string $url URL to redirect.
  225. * @return \yii\web\Response response instance.
  226. */
  227. public function redirectSuccess($url = null)
  228. {
  229. if ($url === null) {
  230. $url = $this->getSuccessUrl();
  231. }
  232. return $this->redirect($url);
  233. }
  234. /**
  235. * Redirect to the [[cancelUrl]] or simply close the popup window.
  236. * @param string $url URL to redirect.
  237. * @return \yii\web\Response response instance.
  238. */
  239. public function redirectCancel($url = null)
  240. {
  241. if ($url === null) {
  242. $url = $this->getCancelUrl();
  243. }
  244. return $this->redirect($url, false);
  245. }
  246. /**
  247. * Performs OpenID auth flow.
  248. * @param OpenId $client auth client instance.
  249. * @return Response action response.
  250. * @throws Exception on failure.
  251. * @throws HttpException on failure.
  252. */
  253. protected function authOpenId($client)
  254. {
  255. if (!empty($_REQUEST['openid_mode'])) {
  256. switch ($_REQUEST['openid_mode']) {
  257. case 'id_res':
  258. if ($client->validate()) {
  259. return $this->authSuccess($client);
  260. } else {
  261. throw new HttpException(400, 'Unable to complete the authentication because the required data was not received.');
  262. }
  263. break;
  264. case 'cancel':
  265. $this->redirectCancel();
  266. break;
  267. default:
  268. throw new HttpException(400);
  269. break;
  270. }
  271. } else {
  272. $url = $client->buildAuthUrl();
  273. return Yii::$app->getResponse()->redirect($url);
  274. }
  275. return $this->redirectCancel();
  276. }
  277. /**
  278. * Performs OAuth1 auth flow.
  279. * @param OAuth1 $client auth client instance.
  280. * @return Response action response.
  281. */
  282. protected function authOAuth1($client)
  283. {
  284. // user denied error
  285. if (isset($_GET['denied'])) {
  286. return $this->redirectCancel();
  287. }
  288. if (isset($_REQUEST['oauth_token'])) {
  289. // Upgrade to access token.
  290. $client->fetchAccessToken($_REQUEST['oauth_token']);
  291. return $this->authSuccess($client);
  292. }
  293. // Get request token.
  294. $requestToken = $client->fetchRequestToken();
  295. // Get authorization URL.
  296. $url = $client->buildAuthUrl($requestToken);
  297. // Redirect to authorization URL.
  298. return Yii::$app->getResponse()->redirect($url);
  299. }
  300. /**
  301. * Performs OAuth2 auth flow.
  302. * @param OAuth2 $client auth client instance.
  303. * @return Response action response.
  304. * @throws \yii\base\Exception on failure.
  305. */
  306. protected function authOAuth2($client)
  307. {
  308. if (isset($_GET['error'])) {
  309. if ($_GET['error'] == 'access_denied') {
  310. // user denied error
  311. return $this->redirectCancel();
  312. } else {
  313. // request error
  314. if (isset($_GET['error_description'])) {
  315. $errorMessage = $_GET['error_description'];
  316. } elseif (isset($_GET['error_message'])) {
  317. $errorMessage = $_GET['error_message'];
  318. } else {
  319. $errorMessage = http_build_query($_GET);
  320. }
  321. throw new Exception('Auth error: ' . $errorMessage);
  322. }
  323. }
  324. // Get the access_token and save them to the session.
  325. if (isset($_GET['code'])) {
  326. $code = $_GET['code'];
  327. $token = $client->fetchAccessToken($code);
  328. if (!empty($token)) {
  329. return $this->authSuccess($client);
  330. } else {
  331. return $this->redirectCancel();
  332. }
  333. } else {
  334. $url = $client->buildAuthUrl();
  335. return Yii::$app->getResponse()->redirect($url);
  336. }
  337. }
  338. }