/Facebook/FacebookSessionPersistence.php

http://github.com/FriendsOfSymfony/FOSFacebookBundle · PHP · 199 lines · 121 code · 30 blank · 48 comment · 12 complexity · 06e932406dd06efad4b03631587c1fda MD5 · raw file

  1. <?php
  2. namespace FOS\FacebookBundle\Facebook;
  3. use Symfony\Component\HttpFoundation\Session\Session;
  4. use Symfony\Component\HttpFoundation\Request;
  5. /**
  6. * Implements Symfony2 session persistence for Facebook.
  7. *
  8. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  9. */
  10. class FacebookSessionPersistence extends \BaseFacebook
  11. {
  12. const PREFIX = '_fos_facebook_';
  13. protected $session;
  14. protected $prefix;
  15. protected static $kSupportedKeys = array('state', 'code', 'access_token', 'user_id');
  16. /**
  17. * @param array $config
  18. * @param Session $session
  19. * @param string $prefix
  20. */
  21. public function __construct($config, Session $session, $prefix = self::PREFIX)
  22. {
  23. $this->session = $session;
  24. $this->prefix = $prefix;
  25. $this->setAppId($config['appId']);
  26. $this->setAppSecret($config['secret']);
  27. if (isset($config['fileUpload'])) {
  28. $this->setFileUploadSupport($config['fileUpload']);
  29. }
  30. // Add trustProxy configuration
  31. $this->trustForwarded = isset($config['trustForwarded']) ? $config['trustForwarded'] : Request::getTrustedProxies();
  32. }
  33. /**
  34. * @param array $params
  35. * @return string
  36. */
  37. public function getLoginUrl($params = array())
  38. {
  39. $this->establishCSRFTokenState();
  40. $currentUrl = $this->getCurrentUrl();
  41. // if 'scope' is passed as an array, convert to comma separated list
  42. $scopeParams = isset($params['scope']) ? $params['scope'] : null;
  43. if ($scopeParams && is_array($scopeParams)) {
  44. $params['scope'] = implode(',', $scopeParams);
  45. }
  46. return $this->getUrl(
  47. 'www',
  48. 'dialog/oauth',
  49. array_merge(
  50. array(
  51. 'client_id' => $this->getAppId(),
  52. 'redirect_uri' => $currentUrl, // possibly overwritten
  53. 'state' => $this->getState(),
  54. ),
  55. $params
  56. )
  57. );
  58. }
  59. /**
  60. * @return bool|mixed
  61. */
  62. protected function getCode()
  63. {
  64. if (isset($_REQUEST['code'])) {
  65. if ($this->getState() !== null &&
  66. isset($_REQUEST['state']) &&
  67. $this->getState() === $_REQUEST['state']) {
  68. // CSRF state has done its job, so clear it
  69. $this->setState(null);
  70. $this->clearPersistentData('state');
  71. return $_REQUEST['code'];
  72. } else {
  73. self::errorLog('CSRF state token does not match one provided.');
  74. return false;
  75. }
  76. }
  77. return false;
  78. }
  79. protected function establishCSRFTokenState()
  80. {
  81. if ($this->getState() === null) {
  82. $this->setState(md5(uniqid(mt_rand(), true)));
  83. }
  84. }
  85. /**
  86. * Stores the given ($key, $value) pair, so that future calls to
  87. * getPersistentData($key) return $value. This call may be in another request.
  88. *
  89. * @param string $key
  90. * @param array $value
  91. *
  92. * @return void
  93. */
  94. protected function setPersistentData($key, $value)
  95. {
  96. if (!in_array($key, self::$kSupportedKeys)) {
  97. self::errorLog('Unsupported key passed to setPersistentData.');
  98. return;
  99. }
  100. $this->session->set($this->constructSessionVariableName($key), $value);
  101. }
  102. /**
  103. * Get the data for $key, persisted by BaseFacebook::setPersistentData()
  104. *
  105. * @param string $key The key of the data to retrieve
  106. * @param boolean $default The default value to return if $key is not found
  107. *
  108. * @return mixed
  109. */
  110. protected function getPersistentData($key, $default = false)
  111. {
  112. if (!in_array($key, self::$kSupportedKeys)) {
  113. self::errorLog('Unsupported key passed to getPersistentData.');
  114. return $default;
  115. }
  116. $sessionVariableName = $this->constructSessionVariableName($key);
  117. if ($this->session->has($sessionVariableName)) {
  118. return $this->session->get($sessionVariableName);
  119. }
  120. return $default;
  121. }
  122. /**
  123. * Clear the data with $key from the persistent storage
  124. *
  125. * @param string $key
  126. * @return void
  127. */
  128. protected function clearPersistentData($key)
  129. {
  130. if (!in_array($key, self::$kSupportedKeys)) {
  131. self::errorLog('Unsupported key passed to clearPersistentData.');
  132. return;
  133. }
  134. $this->session->remove($this->constructSessionVariableName($key));
  135. }
  136. /**
  137. * Clear all data from the persistent storage
  138. *
  139. * @return void
  140. */
  141. protected function clearAllPersistentData()
  142. {
  143. foreach ($this->session->all() as $k => $v) {
  144. if (0 !== strpos($k, $this->prefix)) {
  145. continue;
  146. }
  147. $this->session->remove($k);
  148. }
  149. }
  150. protected function constructSessionVariableName($key)
  151. {
  152. return $this->prefix.implode(
  153. '_',
  154. array(
  155. 'fb',
  156. $this->getAppId(),
  157. $key,
  158. )
  159. );
  160. }
  161. private function getState()
  162. {
  163. return $this->getPersistentData('state', null);
  164. }
  165. private function setState($state)
  166. {
  167. $this->setPersistentData('state', $state);
  168. }
  169. }