BxGoogleConModule.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  4. * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  5. *
  6. * @defgroup GoogleConnect Google Connect
  7. * @ingroup TridentModules
  8. *
  9. * @{
  10. */
  11. class BxGoogleConModule extends BxBaseModConnectModule
  12. {
  13. function __construct(&$aModule)
  14. {
  15. parent::__construct($aModule);
  16. }
  17. /**
  18. * Generate admin page;
  19. *
  20. * @return : (text) - html presentation data;
  21. */
  22. function actionAdministration()
  23. {
  24. parent::_actionAdministration('bx_googlecon_api_key', '_bx_googlecon_settings', '_bx_googlecon_information', '_bx_googlecon_information_block');
  25. }
  26. /**
  27. * Redirect to remote site login form
  28. *
  29. * @return n/a - redirect or HTML page in case of error
  30. */
  31. function actionStart()
  32. {
  33. if (isLogged())
  34. $this->_redirect ($this -> _oConfig -> sDefaultRedirectUrl);
  35. if (!$this->_oConfig->sApiID || !$this->_oConfig->sApiSecret) {
  36. require_once(BX_DIRECTORY_PATH_INC . 'design.inc.php');
  37. bx_import('BxDolLanguages');
  38. $sCode = MsgBox( _t('_bx_googlecon_profile_error_api_keys') );
  39. $this->_oTemplate->getPage(_t('_bx_googlecon'), $sCode);
  40. }
  41. else {
  42. // define redirect URL to the remote site
  43. $sUrl = bx_append_url_params($this->_oConfig->sOauthUrl . '/auth', array(
  44. 'response_type' => 'code',
  45. 'client_id' => $this->_oConfig->sApiID,
  46. 'redirect_uri' => $this->_oConfig->sPageHandle,
  47. 'scope' => $this->_oConfig->sScope,
  48. 'state' => $this->_genCsrfToken(),
  49. ));
  50. $this->_redirect($sUrl);
  51. }
  52. }
  53. function actionHandle()
  54. {
  55. require_once(BX_DIRECTORY_PATH_INC . 'design.inc.php');
  56. // check CSRF token
  57. if ($this->_getCsrfToken() != bx_get('state')) {
  58. $this->_oTemplate->getPage(_t('_Error'), MsgBox(_t('_bx_googlecon_state_invalid')));
  59. return;
  60. }
  61. // check code
  62. $sCode = bx_get('code');
  63. if (!$sCode || bx_get('error')) {
  64. $sErrorDescription = bx_get('error_description') ? bx_get('error_description') : _t('_error occured');
  65. $this->_oTemplate->getPage(_t('_Error'), MsgBox($sErrorDescription));
  66. return;
  67. }
  68. // make request for token
  69. $s = bx_file_get_contents($this->_oConfig->sApiUrl . '/oauth2/v4/token', array(
  70. 'client_id' => $this->_oConfig->sApiID,
  71. 'client_secret' => $this->_oConfig->sApiSecret,
  72. 'grant_type' => 'authorization_code',
  73. 'code' => $sCode,
  74. 'redirect_uri' => $this->_oConfig->sPageHandle,
  75. ), 'post', array ('Content-Type: application/x-www-form-urlencoded'));
  76. // handle error
  77. if (!$s || NULL === ($aResponse = json_decode($s, true)) || !isset($aResponse['access_token']) || isset($aResponse['error'])) {
  78. $sErrorDescription = isset($aResponse['error_description']) ? $aResponse['error_description'] : _t('_error occured');
  79. $this->_oTemplate->getPage(_t('_Error'), MsgBox($sErrorDescription));
  80. return;
  81. }
  82. // get the data, especially access_token
  83. $sAccessToken = $aResponse['access_token'];
  84. $sExpiresIn = $aResponse['expires_in'];
  85. $sExpiresAt = new \DateTime('+' . $sExpiresIn . ' seconds');
  86. // request info about profile
  87. $s = bx_file_get_contents($this->_oConfig->sApiUrl . '/oauth2/v1/userinfo', array(), 'get', array(
  88. 'Authorization: Bearer ' . $sAccessToken,
  89. ));
  90. // handle error
  91. if (!$s || NULL === ($aResponse = json_decode($s, true)) || !$aResponse || isset($aResponse['error'])) {
  92. $sErrorDescription = isset($aResponse['error_description']) ? $aResponse['error_description'] : _t('_error occured');
  93. $this->_oTemplate->getPage(_t('_Error'), MsgBox($sErrorDescription));
  94. return;
  95. }
  96. $aRemoteProfileInfo = $aResponse;
  97. if ($aRemoteProfileInfo) {
  98. // check if user logged in before
  99. $iLocalProfileId = $this->_oDb->getProfileId($aRemoteProfileInfo['id']);
  100. if ($iLocalProfileId && $oProfile = BxDolProfile::getInstance($iLocalProfileId)) {
  101. // user already exists
  102. $this->setLogged($oProfile ->id());
  103. }
  104. else {
  105. // register new user
  106. $this->_createProfile($aRemoteProfileInfo);
  107. }
  108. }
  109. else {
  110. $this->_oTemplate->getPage(_t('_Error'), MsgBox(_t('_bx_googlecon_profile_error_info')));
  111. }
  112. }
  113. protected function _redirect($sUrl, $iStatus = 302)
  114. {
  115. header("Location:{$sUrl}", true, $iStatus);
  116. exit;
  117. }
  118. /**
  119. * @param $aProfileInfo - remote profile info
  120. * @param $sAlternativeName - suffix to add to NickName to make it unique
  121. * @return profile array info, ready for the local database
  122. */
  123. protected function _convertRemoteFields($aProfileInfo, $sAlternativeName = '')
  124. {
  125. $aProfileFields = $aProfileInfo;
  126. $aProfileFields['name'] = $aProfileInfo['given_name'];
  127. $aProfileFields['fullname'] = $aProfileInfo['name'];
  128. $aProfileFields['email'] = isset($aProfileInfo['email']) ? $aProfileInfo['email'] : '';
  129. $aProfileFields['picture'] = isset($aProfileInfo['picture']) ? $aProfileInfo['picture'] : '';
  130. return $aProfileFields;
  131. }
  132. protected function _genCsrfToken($bReturn = false)
  133. {
  134. if (getParam('sys_security_form_token_enable') != 'on' || defined('BX_DOL_CRON_EXECUTE'))
  135. return false;
  136. $oSession = BxDolSession::getInstance();
  137. $iCsrfTokenLifetime = (int)$this->_oDb->getParam('sys_security_form_token_lifetime');
  138. if ($oSession->getValue('bx_googlecon_csrf_token') === false || ($iCsrfTokenLifetime != 0 && time() - (int)$oSession->getValue('csrf_token_time') > $iCsrfTokenLifetime)) {
  139. $sToken = genRndPwd(20, false);
  140. $oSession->setValue('bx_googlecon_csrf_token', $sToken);
  141. $oSession->setValue('bx_googlecon_csrf_token_time', time());
  142. }
  143. else {
  144. $sToken = $oSession->getValue('bx_googlecon_csrf_token');
  145. }
  146. return $sToken;
  147. }
  148. protected function _getCsrfToken()
  149. {
  150. $oSession = BxDolSession::getInstance();
  151. return $oSession->getValue('bx_googlecon_csrf_token');
  152. }
  153. }
  154. /** @} */