PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Logica/Facebook/Helpers/FacebookRedirectLoginHelper.php

https://gitlab.com/ifelipa/Proyecto-DAW
PHP | 360 lines | 146 code | 42 blank | 172 comment | 12 complexity | e0bc282f269891c1d7eee5eb2a343512 MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright 2014 Facebook, Inc.
  4. *
  5. * You are hereby granted a non-exclusive, worldwide, royalty-free license to
  6. * use, copy, modify, and distribute this software in source code or binary
  7. * form for use in connection with the web services and APIs provided by
  8. * Facebook.
  9. *
  10. * As with any software that integrates with the Facebook platform, your use
  11. * of this software is subject to the Facebook Developer Principles and
  12. * Policies [http://developers.facebook.com/policy/]. This copyright notice
  13. * shall be included in all copies or substantial portions of the software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. *
  23. */
  24. namespace Facebook\Helpers;
  25. use Facebook\Authentication\AccessToken;
  26. use Facebook\Authentication\OAuth2Client;
  27. use Facebook\Url\UrlDetectionInterface;
  28. use Facebook\Url\FacebookUrlDetectionHandler;
  29. use Facebook\Url\FacebookUrlManipulator;
  30. use Facebook\PersistentData\PersistentDataInterface;
  31. use Facebook\PersistentData\FacebookSessionPersistentDataHandler;
  32. use Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface;
  33. use Facebook\PseudoRandomString\McryptPseudoRandomStringGenerator;
  34. use Facebook\PseudoRandomString\OpenSslPseudoRandomStringGenerator;
  35. use Facebook\PseudoRandomString\UrandomPseudoRandomStringGenerator;
  36. use Facebook\Exceptions\FacebookSDKException;
  37. /**
  38. * Class FacebookRedirectLoginHelper
  39. *
  40. * @package Facebook
  41. */
  42. class FacebookRedirectLoginHelper
  43. {
  44. /**
  45. * @const int The length of CSRF string to validate the login link.
  46. */
  47. const CSRF_LENGTH = 32;
  48. /**
  49. * @var OAuth2Client The OAuth 2.0 client service.
  50. */
  51. protected $oAuth2Client;
  52. /**
  53. * @var UrlDetectionInterface The URL detection handler.
  54. */
  55. protected $urlDetectionHandler;
  56. /**
  57. * @var PersistentDataInterface The persistent data handler.
  58. */
  59. protected $persistentDataHandler;
  60. /**
  61. * @var PseudoRandomStringGeneratorInterface The cryptographically secure pseudo-random string generator.
  62. */
  63. protected $pseudoRandomStringGenerator;
  64. /**
  65. * @param OAuth2Client $oAuth2Client The OAuth 2.0 client service.
  66. * @param PersistentDataInterface|null $persistentDataHandler The persistent data handler.
  67. * @param UrlDetectionInterface|null $urlHandler The URL detection handler.
  68. * @param PseudoRandomStringGeneratorInterface|null $prsg The cryptographically secure pseudo-random string generator.
  69. */
  70. public function __construct(OAuth2Client $oAuth2Client, PersistentDataInterface $persistentDataHandler = null, UrlDetectionInterface $urlHandler = null, PseudoRandomStringGeneratorInterface $prsg = null)
  71. {
  72. $this->oAuth2Client = $oAuth2Client;
  73. $this->persistentDataHandler = $persistentDataHandler ?: new FacebookSessionPersistentDataHandler();
  74. $this->urlDetectionHandler = $urlHandler ?: new FacebookUrlDetectionHandler();
  75. $this->pseudoRandomStringGenerator = $prsg ?: $this->detectPseudoRandomStringGenerator();
  76. }
  77. /**
  78. * Returns the persistent data handler.
  79. *
  80. * @return PersistentDataInterface
  81. */
  82. public function getPersistentDataHandler()
  83. {
  84. return $this->persistentDataHandler;
  85. }
  86. /**
  87. * Returns the URL detection handler.
  88. *
  89. * @return UrlDetectionInterface
  90. */
  91. public function getUrlDetectionHandler()
  92. {
  93. return $this->urlDetectionHandler;
  94. }
  95. /**
  96. * Returns the cryptographically secure pseudo-random string generator.
  97. *
  98. * @return PseudoRandomStringGeneratorInterface
  99. */
  100. public function getPseudoRandomStringGenerator()
  101. {
  102. return $this->pseudoRandomStringGenerator;
  103. }
  104. /**
  105. * Detects which pseudo-random string generator to use.
  106. *
  107. * @return PseudoRandomStringGeneratorInterface
  108. *
  109. * @throws FacebookSDKException
  110. */
  111. public function detectPseudoRandomStringGenerator()
  112. {
  113. // Since openssl_random_pseudo_bytes() can sometimes return non-cryptographically
  114. // secure pseudo-random strings (in rare cases), we check for mcrypt_create_iv() first.
  115. if (function_exists('mcrypt_create_iv')) {
  116. return new McryptPseudoRandomStringGenerator();
  117. }
  118. if (function_exists('openssl_random_pseudo_bytes')) {
  119. return new OpenSslPseudoRandomStringGenerator();
  120. }
  121. if (!ini_get('open_basedir') && is_readable('/dev/urandom')) {
  122. return new UrandomPseudoRandomStringGenerator();
  123. }
  124. throw new FacebookSDKException('Unable to detect a cryptographically secure pseudo-random string generator.');
  125. }
  126. /**
  127. * Stores CSRF state and returns a URL to which the user should be sent to in order to continue the login process with Facebook.
  128. *
  129. * @param string $redirectUrl The URL Facebook should redirect users to after login.
  130. * @param array $scope List of permissions to request during login.
  131. * @param array $params An array of parameters to generate URL.
  132. * @param string $separator The separator to use in http_build_query().
  133. *
  134. * @return string
  135. */
  136. private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&')
  137. {
  138. $state = $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH);
  139. $this->persistentDataHandler->set('state', $state);
  140. return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator);
  141. }
  142. /**
  143. * Returns the URL to send the user in order to login to Facebook.
  144. *
  145. * @param string $redirectUrl The URL Facebook should redirect users to after login.
  146. * @param array $scope List of permissions to request during login.
  147. * @param string $separator The separator to use in http_build_query().
  148. *
  149. * @return string
  150. */
  151. public function getLoginUrl($redirectUrl, array $scope = [], $separator = '&')
  152. {
  153. return $this->makeUrl($redirectUrl, $scope, [], $separator);
  154. }
  155. /**
  156. * Returns the URL to send the user in order to log out of Facebook.
  157. *
  158. * @param AccessToken|string $accessToken The access token that will be logged out.
  159. * @param string $next The url Facebook should redirect the user to after a successful logout.
  160. * @param string $separator The separator to use in http_build_query().
  161. *
  162. * @return string
  163. *
  164. * @throws FacebookSDKException
  165. */
  166. public function getLogoutUrl($accessToken, $next, $separator = '&')
  167. {
  168. if (!$accessToken instanceof AccessToken) {
  169. $accessToken = new AccessToken($accessToken);
  170. }
  171. if ($accessToken->isAppAccessToken()) {
  172. throw new FacebookSDKException('Cannot generate a logout URL with an app access token.', 722);
  173. }
  174. $params = [
  175. 'next' => $next,
  176. 'access_token' => $accessToken->getValue(),
  177. ];
  178. return 'https://www.facebook.com/logout.php?' . http_build_query($params, null, $separator);
  179. }
  180. /**
  181. * Returns the URL to send the user in order to login to Facebook with permission(s) to be re-asked.
  182. *
  183. * @param string $redirectUrl The URL Facebook should redirect users to after login.
  184. * @param array $scope List of permissions to request during login.
  185. * @param string $separator The separator to use in http_build_query().
  186. *
  187. * @return string
  188. */
  189. public function getReRequestUrl($redirectUrl, array $scope = [], $separator = '&')
  190. {
  191. $params = ['auth_type' => 'rerequest'];
  192. return $this->makeUrl($redirectUrl, $scope, $params, $separator);
  193. }
  194. /**
  195. * Returns the URL to send the user in order to login to Facebook with user to be re-authenticated.
  196. *
  197. * @param string $redirectUrl The URL Facebook should redirect users to after login.
  198. * @param array $scope List of permissions to request during login.
  199. * @param string $separator The separator to use in http_build_query().
  200. *
  201. * @return string
  202. */
  203. public function getReAuthenticationUrl($redirectUrl, array $scope = [], $separator = '&')
  204. {
  205. $params = ['auth_type' => 'reauthenticate'];
  206. return $this->makeUrl($redirectUrl, $scope, $params, $separator);
  207. }
  208. /**
  209. * Takes a valid code from a login redirect, and returns an AccessToken entity.
  210. *
  211. * @param string|null $redirectUrl The redirect URL.
  212. *
  213. * @return AccessToken|null
  214. *
  215. * @throws FacebookSDKException
  216. */
  217. public function getAccessToken($redirectUrl = null)
  218. {
  219. if (!$code = $this->getCode()) {
  220. return null;
  221. }
  222. $this->validateCsrf();
  223. $redirectUrl = $redirectUrl ?: $this->urlDetectionHandler->getCurrentUrl();
  224. // At minimum we need to remove the state param
  225. $redirectUrl = FacebookUrlManipulator::removeParamsFromUrl($redirectUrl, ['state']);
  226. return $this->oAuth2Client->getAccessTokenFromCode($code, $redirectUrl);
  227. }
  228. /**
  229. * Validate the request against a cross-site request forgery.
  230. *
  231. * @throws FacebookSDKException
  232. */
  233. protected function validateCsrf()
  234. {
  235. $state = $this->getState();
  236. $savedState = $this->persistentDataHandler->get('state');
  237. if (!$state || !$savedState) {
  238. throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing.');
  239. }
  240. $savedLen = strlen($savedState);
  241. $givenLen = strlen($state);
  242. if ($savedLen !== $givenLen) {
  243. throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
  244. }
  245. $result = 0;
  246. for ($i = 0; $i < $savedLen; $i++) {
  247. $result |= ord($state[$i]) ^ ord($savedState[$i]);
  248. }
  249. if ($result !== 0) {
  250. throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
  251. }
  252. }
  253. /**
  254. * Return the code.
  255. *
  256. * @return string|null
  257. */
  258. protected function getCode()
  259. {
  260. return $this->getInput('code');
  261. }
  262. /**
  263. * Return the state.
  264. *
  265. * @return string|null
  266. */
  267. protected function getState()
  268. {
  269. return $this->getInput('state');
  270. }
  271. /**
  272. * Return the error code.
  273. *
  274. * @return string|null
  275. */
  276. public function getErrorCode()
  277. {
  278. return $this->getInput('error_code');
  279. }
  280. /**
  281. * Returns the error.
  282. *
  283. * @return string|null
  284. */
  285. public function getError()
  286. {
  287. return $this->getInput('error');
  288. }
  289. /**
  290. * Returns the error reason.
  291. *
  292. * @return string|null
  293. */
  294. public function getErrorReason()
  295. {
  296. return $this->getInput('error_reason');
  297. }
  298. /**
  299. * Returns the error description.
  300. *
  301. * @return string|null
  302. */
  303. public function getErrorDescription()
  304. {
  305. return $this->getInput('error_description');
  306. }
  307. /**
  308. * Returns a value from a GET param.
  309. *
  310. * @param string $key
  311. *
  312. * @return string|null
  313. */
  314. private function getInput($key)
  315. {
  316. return isset($_GET[$key]) ? $_GET[$key] : null;
  317. }
  318. }