Skip to content
This repository has been archived by the owner on Sep 10, 2021. It is now read-only.

Commit

Permalink
Refactor Google Authentication module
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamie Snape committed Oct 21, 2015
1 parent 0d4bfd9 commit f87ec17
Show file tree
Hide file tree
Showing 14 changed files with 256 additions and 176 deletions.
4 changes: 4 additions & 0 deletions core/controllers/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ public function recoverpasswordAction()
public function logoutAction()
{
session_start(); // we closed session before, must restart it to logout
$notifier = new MIDAS_Notifier(false, null);
$notifier->callback('CALLBACK_CORE_USER_LOGOUT');
$this->userSession->Dao = null;
Zend_Session::ForgetMe();
$request = $this->getRequest();
Expand Down Expand Up @@ -1322,6 +1324,8 @@ public function deleteAction()
$this->requireAdminPrivileges();
} else {
// log out if user is deleting his or her own account
$notifier = new MIDAS_Notifier(false, null);
$notifier->callback('CALLBACK_CORE_USER_LOGOUT');
if (!$this->isTestingEnv()) {
session_start();
$this->userSession->Dao = null;
Expand Down
139 changes: 104 additions & 35 deletions modules/googleauth/Notification.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,20 @@
limitations under the License.
=========================================================================*/

/** Notification manager for the googleauth module */
/**
* Notification manager for the googleauth module.
*
* @property Googleauth_UserModel $Googleauth_User
*/
class Googleauth_Notification extends MIDAS_Notification
{
/** @var string */
public $moduleName = 'googleauth';

/** @var array */
public $_models = array('Setting', 'User', 'Userapi');

/** @var array */
public $_moduleModels = array('User');

/** init notification process */
Expand All @@ -31,76 +40,136 @@ public function init()
$this->addCallBack('CALLBACK_CORE_LOGIN_EXTRA_HTML', 'googleAuthLink');
$this->addCallBack('CALLBACK_CORE_USER_DELETED', 'handleUserDeleted');
$this->addCallBack('CALLBACK_CORE_USER_COOKIE', 'checkUserCookie');
$this->addCallBack('CALLBACK_CORE_USER_LOGOUT', 'handleUserLogout');
}

/**
* Constructs the link that is used to initiate a google oauth authentication.
* This link redirects the user to google so they can approve of the requested
* oauth scopes, and in turn google will redirect them back to our callback
* url with an authorization code.
*
* @return string
*/
public function googleAuthLink()
{
$baseUrl = Zend_Controller_Front::getInstance()->getBaseUrl();

$clientId = $this->Setting->getValueByName(GOOGLE_AUTH_CLIENT_ID_KEY, $this->moduleName);
$scheme = (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS']) ? 'https://' : 'http://';
$fc = Zend_Controller_Front::getInstance();
$redirectUri = UtilityComponent::getServerURL().$baseUrl.'/'.$this->moduleName.'/callback';
$additionalScopes = preg_split('/\n|\r/', $this->Setting->getValueByName(GOOGLE_AUTH_CLIENT_ADDITIONAL_SCOPES_KEY, $this->moduleName), -1, PREG_SPLIT_NO_EMPTY);

/** @var RandomComponent $randomComponent */
$randomComponent = MidasLoader::loadComponent('Random');
$csrfToken = $randomComponent->generateString(30);
$redirectUri = $scheme.$_SERVER['HTTP_HOST'].$fc->getBaseUrl().'/'.$this->moduleName.'/callback';
$scopes = array('profile', 'email');

$href = 'https://accounts.google.com/o/oauth2/auth?response_type=code'.'&client_id='.urlencode(
$clientId
).'&redirect_uri='.urlencode($redirectUri).'&scope='.urlencode(
implode(
' ',
$scopes
)
).'&state='.urlencode($csrfToken);

$userNs = new Zend_Session_Namespace('Auth_User');
$userNs->oauthToken = $csrfToken;
$csrf = $randomComponent->generateString(32);

$client = new Google_Client();
$client->setAccessType('offline');
$client->setClientId($clientId);
$client->setRedirectUri($redirectUri);
$client->setScopes(array_merge(array('email', 'profile'), $additionalScopes));
$client->setState($csrf);

$namespace = new Zend_Session_Namespace('Auth_User');
$namespace->oauthToken = $csrf;
session_write_close();

return '<div style="margin-top: 10px; display: inline-block;">Or '.'<a class="googleauth-login" style="text-decoration: underline;" href="'.htmlspecialchars($href, ENT_QUOTES, 'UTF-8').'">'.'Login with your Google account</a></div><script type="text/javascript"'.' src="'.$fc->getBaseUrl(
).'/modules/'.$this->moduleName.'/public/js/login/googleauth.login.js"></script>';
$authUrl = $client->createAuthUrl();

return '<div style="margin-top: 10px; display: inline-block;">Or '.'<a class="googleauth-login" style="text-decoration: underline;" href="'.htmlspecialchars($authUrl, ENT_QUOTES, 'UTF-8').'">'.'Login with your Google account</a></div><script type="text/javascript"'.' src="'.UtilityComponent::getServerURL().$baseUrl.'/modules/'.$this->moduleName.'/public/js/login/googleauth.login.js"></script>';
}

/**
* If a user is deleted, we must delete any corresponding google auth user.
*
* @param array $args
*/
public function handleUserDeleted($params)
public function handleUserDeleted($args)
{
$this->Googleauth_User->deleteByUser($params['userDao']);
$this->Googleauth_User->deleteByUser($args['userDao']);
}

/** Check user cookie */
/**
* Check user cookie.
*
* @param array $args
* @return false|UserDao
* @throws Zend_Exception
*/
public function checkUserCookie($args)
{
$cookie = $args['value'];

if (strpos($cookie, 'googleauth') === 0) {
list(, $userId, $apikey) = preg_split('/:/', $cookie);
$userDao = $this->User->load($userId);
list(, $userId, $apiKey) = preg_split('/:/', $cookie);

if (!$userDao) {
$userDao = $this->User->load($userId);
if ($userDao === false) {
return false;
}

$userapi = $this->Userapi->getByAppAndUser('Default', $userDao);

if (!$userapi) {
$userApiDao = $this->Userapi->getByAppAndUser('Default', $userDao);
if ($userApiDao === false || md5($userApiDao->getApikey()) !== $apiKey) {
return false;
}
if (md5($userapi->getApikey()) === $apikey) {
return $userDao;
} else {
return false;

/** @var Zend_Controller_Request_Http $request */
$request = Zend_Controller_Front::getInstance()->getRequest();
$accessToken = $request->getCookie(GOOGLE_AUTH_ACCESS_TOKEN_COOKIE_NAME, false);

if ($accessToken !== false) {
$clientId = $this->Setting->getValueByName(GOOGLE_AUTH_CLIENT_ID_KEY, $this->moduleName);
$clientSecret = $this->Setting->getValueByName(GOOGLE_AUTH_CLIENT_SECRET_KEY, $this->moduleName);

$client = new Google_Client();
$client->setAccessToken($accessToken);
$client->setAccessType('offline');
$client->setClientId($clientId);
$client->setClientSecret($clientSecret);

if ($client->isAccessTokenExpired()) {
$refreshToken = $client->getRefreshToken();
$client->refreshToken($refreshToken);

$date = new DateTime();
$interval = new DateInterval('P1M');
setcookie(
GOOGLE_AUTH_ACCESS_TOKEN_COOKIE_NAME,
$client->getAccessToken(),
$date->add($interval)->getTimestamp(),
'/',
$request->getHttpHost(),
(int) Zend_Registry::get('configGlobal')->get('cookie_secure', 1) === 1,
true
);
}
}
} else {
return false;

return $userDao;
}

return false;
}

/**
* Handle the core CALLBACK_CORE_USER_LOGOUT notification.
*
* @param array $args
*/
public function handleUserLogout($args)
{
/** @var Zend_Controller_Request_Http $request */
$request = Zend_Controller_Front::getInstance()->getRequest();
$date = new DateTime();
$interval = new DateInterval('P1M');
setcookie(
GOOGLE_AUTH_ACCESS_TOKEN_COOKIE_NAME,
null,
$date->sub($interval)->getTimestamp(),
'/',
$request->getHttpHost(),
(int) Zend_Registry::get('configGlobal')->get('cookie_secure', 1) === 1,
true
);
}
}
2 changes: 1 addition & 1 deletion modules/googleauth/configs/module.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ description = "Authenticate users using Google accounts"
category = "Authentication"
dependencies = api
uuid = "1f331c86-b1ca-4b42-ba49-5102aed4965e"
version = "1.1.0"
version = "1.1.1"
6 changes: 4 additions & 2 deletions modules/googleauth/constant/module.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
limitations under the License.
=========================================================================*/

define('GOOGLE_AUTH_ACCESS_TOKEN_COOKIE_NAME', 'wnka5bnrkmvhzybg9w8ezckrjn6hnk6awpwxtkxb');

define('GOOGLE_AUTH_CLIENT_ID_KEY', 'client_id');
define('GOOGLE_AUTH_CLIENT_ID_DEFAULT_VALUE', '');

define('GOOGLE_AUTH_CLIENT_SECRET_KEY', 'client_secret');
define('GOOGLE_AUTH_CLIENT_SECRET_DEFAULT_VALUE', '');

define('GOOGLE_AUTH_OAUTH2_URL', 'https://accounts.google.com/o/oauth2/token');
define('GOOGLE_AUTH_PLUS_URL', 'https://www.googleapis.com/plus/v1/people/me');
define('GOOGLE_AUTH_CLIENT_ADDITIONAL_SCOPES_KEY', 'additional_scopes');
define('GOOGLE_AUTH_CLIENT_ADDITIONAL_SCOPES_DEFAULT_VALUE', '');
Loading

0 comments on commit f87ec17

Please sign in to comment.