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

Commit f87ec17

Browse files
author
Jamie Snape
committed
Refactor Google Authentication module
1 parent 0d4bfd9 commit f87ec17

File tree

14 files changed

+256
-176
lines changed

14 files changed

+256
-176
lines changed

core/controllers/UserController.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ public function recoverpasswordAction()
154154
public function logoutAction()
155155
{
156156
session_start(); // we closed session before, must restart it to logout
157+
$notifier = new MIDAS_Notifier(false, null);
158+
$notifier->callback('CALLBACK_CORE_USER_LOGOUT');
157159
$this->userSession->Dao = null;
158160
Zend_Session::ForgetMe();
159161
$request = $this->getRequest();
@@ -1322,6 +1324,8 @@ public function deleteAction()
13221324
$this->requireAdminPrivileges();
13231325
} else {
13241326
// log out if user is deleting his or her own account
1327+
$notifier = new MIDAS_Notifier(false, null);
1328+
$notifier->callback('CALLBACK_CORE_USER_LOGOUT');
13251329
if (!$this->isTestingEnv()) {
13261330
session_start();
13271331
$this->userSession->Dao = null;

modules/googleauth/Notification.php

Lines changed: 104 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,20 @@
1818
limitations under the License.
1919
=========================================================================*/
2020

21-
/** Notification manager for the googleauth module */
21+
/**
22+
* Notification manager for the googleauth module.
23+
*
24+
* @property Googleauth_UserModel $Googleauth_User
25+
*/
2226
class Googleauth_Notification extends MIDAS_Notification
2327
{
28+
/** @var string */
2429
public $moduleName = 'googleauth';
30+
31+
/** @var array */
2532
public $_models = array('Setting', 'User', 'Userapi');
33+
34+
/** @var array */
2635
public $_moduleModels = array('User');
2736

2837
/** init notification process */
@@ -31,76 +40,136 @@ public function init()
3140
$this->addCallBack('CALLBACK_CORE_LOGIN_EXTRA_HTML', 'googleAuthLink');
3241
$this->addCallBack('CALLBACK_CORE_USER_DELETED', 'handleUserDeleted');
3342
$this->addCallBack('CALLBACK_CORE_USER_COOKIE', 'checkUserCookie');
43+
$this->addCallBack('CALLBACK_CORE_USER_LOGOUT', 'handleUserLogout');
3444
}
3545

3646
/**
3747
* Constructs the link that is used to initiate a google oauth authentication.
3848
* This link redirects the user to google so they can approve of the requested
3949
* oauth scopes, and in turn google will redirect them back to our callback
4050
* url with an authorization code.
51+
*
52+
* @return string
4153
*/
4254
public function googleAuthLink()
4355
{
56+
$baseUrl = Zend_Controller_Front::getInstance()->getBaseUrl();
57+
4458
$clientId = $this->Setting->getValueByName(GOOGLE_AUTH_CLIENT_ID_KEY, $this->moduleName);
45-
$scheme = (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS']) ? 'https://' : 'http://';
46-
$fc = Zend_Controller_Front::getInstance();
59+
$redirectUri = UtilityComponent::getServerURL().$baseUrl.'/'.$this->moduleName.'/callback';
60+
$additionalScopes = preg_split('/\n|\r/', $this->Setting->getValueByName(GOOGLE_AUTH_CLIENT_ADDITIONAL_SCOPES_KEY, $this->moduleName), -1, PREG_SPLIT_NO_EMPTY);
4761

4862
/** @var RandomComponent $randomComponent */
4963
$randomComponent = MidasLoader::loadComponent('Random');
50-
$csrfToken = $randomComponent->generateString(30);
51-
$redirectUri = $scheme.$_SERVER['HTTP_HOST'].$fc->getBaseUrl().'/'.$this->moduleName.'/callback';
52-
$scopes = array('profile', 'email');
53-
54-
$href = 'https://accounts.google.com/o/oauth2/auth?response_type=code'.'&client_id='.urlencode(
55-
$clientId
56-
).'&redirect_uri='.urlencode($redirectUri).'&scope='.urlencode(
57-
implode(
58-
' ',
59-
$scopes
60-
)
61-
).'&state='.urlencode($csrfToken);
62-
63-
$userNs = new Zend_Session_Namespace('Auth_User');
64-
$userNs->oauthToken = $csrfToken;
64+
$csrf = $randomComponent->generateString(32);
65+
66+
$client = new Google_Client();
67+
$client->setAccessType('offline');
68+
$client->setClientId($clientId);
69+
$client->setRedirectUri($redirectUri);
70+
$client->setScopes(array_merge(array('email', 'profile'), $additionalScopes));
71+
$client->setState($csrf);
72+
73+
$namespace = new Zend_Session_Namespace('Auth_User');
74+
$namespace->oauthToken = $csrf;
6575
session_write_close();
6676

67-
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(
68-
).'/modules/'.$this->moduleName.'/public/js/login/googleauth.login.js"></script>';
77+
$authUrl = $client->createAuthUrl();
78+
79+
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>';
6980
}
7081

7182
/**
7283
* If a user is deleted, we must delete any corresponding google auth user.
84+
*
85+
* @param array $args
7386
*/
74-
public function handleUserDeleted($params)
87+
public function handleUserDeleted($args)
7588
{
76-
$this->Googleauth_User->deleteByUser($params['userDao']);
89+
$this->Googleauth_User->deleteByUser($args['userDao']);
7790
}
7891

79-
/** Check user cookie */
92+
/**
93+
* Check user cookie.
94+
*
95+
* @param array $args
96+
* @return false|UserDao
97+
* @throws Zend_Exception
98+
*/
8099
public function checkUserCookie($args)
81100
{
82101
$cookie = $args['value'];
83102

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

88-
if (!$userDao) {
106+
$userDao = $this->User->load($userId);
107+
if ($userDao === false) {
89108
return false;
90109
}
91110

92-
$userapi = $this->Userapi->getByAppAndUser('Default', $userDao);
93-
94-
if (!$userapi) {
111+
$userApiDao = $this->Userapi->getByAppAndUser('Default', $userDao);
112+
if ($userApiDao === false || md5($userApiDao->getApikey()) !== $apiKey) {
95113
return false;
96114
}
97-
if (md5($userapi->getApikey()) === $apikey) {
98-
return $userDao;
99-
} else {
100-
return false;
115+
116+
/** @var Zend_Controller_Request_Http $request */
117+
$request = Zend_Controller_Front::getInstance()->getRequest();
118+
$accessToken = $request->getCookie(GOOGLE_AUTH_ACCESS_TOKEN_COOKIE_NAME, false);
119+
120+
if ($accessToken !== false) {
121+
$clientId = $this->Setting->getValueByName(GOOGLE_AUTH_CLIENT_ID_KEY, $this->moduleName);
122+
$clientSecret = $this->Setting->getValueByName(GOOGLE_AUTH_CLIENT_SECRET_KEY, $this->moduleName);
123+
124+
$client = new Google_Client();
125+
$client->setAccessToken($accessToken);
126+
$client->setAccessType('offline');
127+
$client->setClientId($clientId);
128+
$client->setClientSecret($clientSecret);
129+
130+
if ($client->isAccessTokenExpired()) {
131+
$refreshToken = $client->getRefreshToken();
132+
$client->refreshToken($refreshToken);
133+
134+
$date = new DateTime();
135+
$interval = new DateInterval('P1M');
136+
setcookie(
137+
GOOGLE_AUTH_ACCESS_TOKEN_COOKIE_NAME,
138+
$client->getAccessToken(),
139+
$date->add($interval)->getTimestamp(),
140+
'/',
141+
$request->getHttpHost(),
142+
(int) Zend_Registry::get('configGlobal')->get('cookie_secure', 1) === 1,
143+
true
144+
);
145+
}
101146
}
102-
} else {
103-
return false;
147+
148+
return $userDao;
104149
}
150+
151+
return false;
152+
}
153+
154+
/**
155+
* Handle the core CALLBACK_CORE_USER_LOGOUT notification.
156+
*
157+
* @param array $args
158+
*/
159+
public function handleUserLogout($args)
160+
{
161+
/** @var Zend_Controller_Request_Http $request */
162+
$request = Zend_Controller_Front::getInstance()->getRequest();
163+
$date = new DateTime();
164+
$interval = new DateInterval('P1M');
165+
setcookie(
166+
GOOGLE_AUTH_ACCESS_TOKEN_COOKIE_NAME,
167+
null,
168+
$date->sub($interval)->getTimestamp(),
169+
'/',
170+
$request->getHttpHost(),
171+
(int) Zend_Registry::get('configGlobal')->get('cookie_secure', 1) === 1,
172+
true
173+
);
105174
}
106175
}

modules/googleauth/configs/module.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ description = "Authenticate users using Google accounts"
66
category = "Authentication"
77
dependencies = api
88
uuid = "1f331c86-b1ca-4b42-ba49-5102aed4965e"
9-
version = "1.1.0"
9+
version = "1.1.1"

modules/googleauth/constant/module.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
limitations under the License.
1919
=========================================================================*/
2020

21+
define('GOOGLE_AUTH_ACCESS_TOKEN_COOKIE_NAME', 'wnka5bnrkmvhzybg9w8ezckrjn6hnk6awpwxtkxb');
22+
2123
define('GOOGLE_AUTH_CLIENT_ID_KEY', 'client_id');
2224
define('GOOGLE_AUTH_CLIENT_ID_DEFAULT_VALUE', '');
2325

2426
define('GOOGLE_AUTH_CLIENT_SECRET_KEY', 'client_secret');
2527
define('GOOGLE_AUTH_CLIENT_SECRET_DEFAULT_VALUE', '');
2628

27-
define('GOOGLE_AUTH_OAUTH2_URL', 'https://accounts.google.com/o/oauth2/token');
28-
define('GOOGLE_AUTH_PLUS_URL', 'https://www.googleapis.com/plus/v1/people/me');
29+
define('GOOGLE_AUTH_CLIENT_ADDITIONAL_SCOPES_KEY', 'additional_scopes');
30+
define('GOOGLE_AUTH_CLIENT_ADDITIONAL_SCOPES_DEFAULT_VALUE', '');

0 commit comments

Comments
 (0)