1: <?php
2: /**
3: * This code is licensed under AGPLv3 license or Afterlogic Software License
4: * if commercial version of the product was purchased.
5: * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
6: */
7:
8: namespace Aurora\Modules\GoogleAuthWebclient;
9:
10: /**
11: * This module adds ability to login using Google account.
12: *
13: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
14: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
15: * @copyright Copyright (c) 2023, Afterlogic Corp.
16: *
17: * @package Modules
18: */
19: class Module extends \Aurora\System\Module\AbstractWebclientModule
20: {
21: protected $sService = 'google';
22:
23: protected $aRequireModules = array(
24: 'OAuthIntegratorWebclient',
25: 'Google'
26: );
27:
28: /***** private functions *****/
29: protected function issetScope($sScope)
30: {
31: return in_array($sScope, explode(' ', $this->getConfig('Scopes')));
32: }
33:
34: /**
35: * Initializes FacebookAuthWebclient Module.
36: *
37: * @ignore
38: */
39: public function init()
40: {
41: $this->subscribeEvent('OAuthIntegratorWebclient::GetServices::after', array($this, 'onAfterGetServices'));
42: $this->subscribeEvent('OAuthIntegratorAction', array($this, 'onOAuthIntegratorAction'));
43: $this->subscribeEvent('Google::GetSettings', array($this, 'onGetSettings'));
44: $this->subscribeEvent('Google::UpdateSettings::after', array($this, 'onAfterUpdateSettings'));
45: $this->subscribeEvent('RevokeAccessToken', array($this, 'onRevokeAccessToken'));
46: $this->subscribeEvent('ResetAccessToken', array($this, 'onResetAccessToken'));
47: $this->subscribeEvent('GetAccessToken', array($this, 'onGetAccessToken'));
48: }
49:
50: /**
51: * Adds service name to array passed by reference.
52: *
53: * @ignore
54: * @param array $aArgs
55: * @param array $aServices Array with services names passed by reference.
56: */
57: public function onAfterGetServices($aArgs, &$aServices)
58: {
59: $oModule = \Aurora\System\Api::GetModule('Google');
60: $sId = $oModule->getConfig('Id', '');
61: $sSecret = $oModule->getConfig('Secret', '');
62:
63: if ($oModule->getConfig('EnableModule', false) && $this->issetScope('auth') && !empty($sId) && !empty($sSecret)) {
64: $aServices[] = $this->sService;
65: }
66: }
67:
68: /**
69: * Passes data to connect to service.
70: *
71: * @ignore
72: * @param string $aArgs Service type to verify if data should be passed.
73: * @param boolean|array $mResult variable passed by reference to take the result.
74: */
75: public function onOAuthIntegratorAction($aArgs, &$mResult)
76: {
77: if (isset($aArgs['Service']) && $aArgs['Service'] === $this->sService) {
78: $sOAuthScopes = isset($_COOKIE['oauth-scopes']) ? $_COOKIE['oauth-scopes'] : '';
79: $aGoogleScopes = [
80: 'https://www.googleapis.com/auth/userinfo.email',
81: 'https://www.googleapis.com/auth/userinfo.profile'
82: ];
83: $this->broadcastEvent('PopulateScopes', $sOAuthScopes, $aGoogleScopes);
84:
85: $mResult = false;
86: $oConnector = new Classes\Connector($this);
87: if ($oConnector) {
88: $oGoogleModule = \Aurora\System\Api::GetModule('Google');
89: if ($oGoogleModule) {
90: $sId = $oGoogleModule->getConfig('Id');
91: $sSecret = $oGoogleModule->getConfig('Secret');
92:
93: $mResult = $oConnector->Init(
94: $sId,
95: $sSecret,
96: [$sOAuthScopes, \implode(' ', $aGoogleScopes)]
97: );
98: }
99: }
100: return true;
101: }
102: }
103:
104: /**
105: * Passes data to connect to service.
106: *
107: * @ignore
108: * @param string $aArgs Service type to verify if data should be passed.
109: * @param boolean|array $mResult variable passed by reference to take the result.
110: */
111: public function onGetSettings($aArgs, &$mResult)
112: {
113: $oUser = \Aurora\System\Api::getAuthenticatedUser();
114:
115: if (!empty($oUser)) {
116: $aScope = array(
117: 'Name' => 'auth',
118: 'Description' => $this->i18N('SCOPE_AUTH'),
119: 'Value' => false
120: );
121: if ($oUser->Role === \Aurora\System\Enums\UserRole::SuperAdmin) {
122: $aScope['Value'] = $this->issetScope('auth');
123: $mResult['Scopes'][] = $aScope;
124: }
125: if ($oUser->isNormalOrTenant()) {
126: if ($aArgs['OAuthAccount'] instanceof \Aurora\Modules\OAuthIntegratorWebclient\Models\OauthAccount) {
127: $aScope['Value'] = $aArgs['OAuthAccount']->issetScope('auth');
128: }
129: if ($this->issetScope('auth')) {
130: $mResult['Scopes'][] = $aScope;
131: }
132: }
133: }
134: }
135:
136: public function onAfterUpdateSettings($aArgs, &$mResult)
137: {
138: $sScope = '';
139: if (isset($aArgs['Scopes']) && is_array($aArgs['Scopes'])) {
140: foreach ($aArgs['Scopes'] as $aScope) {
141: if ($aScope['Name'] === 'auth') {
142: if ($aScope['Value']) {
143: $sScope = 'auth';
144: break;
145: }
146: }
147: }
148: }
149: $this->setConfig('Scopes', $sScope);
150: $this->saveModuleConfig();
151: }
152:
153: public function onRevokeAccessToken($aArgs)
154: {
155: if (isset($aArgs['Service']) && $aArgs['Service'] === $this->sService) {
156: $oConnector = new Classes\Connector($this);
157: if ($oConnector) {
158: $oGoogleModule = \Aurora\System\Api::GetModule('Google');
159: if ($oGoogleModule) {
160: $sAccessToken = isset($aArgs['AccessToken']) ? $aArgs['AccessToken'] : '';
161: $mResult = $oConnector->RevokeAccessToken(
162: $oGoogleModule->getConfig('Id'),
163: $oGoogleModule->getConfig('Secret'),
164: $sAccessToken
165: );
166: }
167: }
168: }
169: }
170:
171: public function onResetAccessToken($aArgs)
172: {
173: if (isset($aArgs['Service']) && $aArgs['Service'] === $this->sService) {
174: $oConnector = new Classes\Connector($this);
175: if ($oConnector) {
176: $oGoogleModule = \Aurora\System\Api::GetModule('Google');
177: if ($oGoogleModule) {
178: $mResult = $oConnector->ResetAccessToken(
179: $oGoogleModule->getConfig('Id'),
180: $oGoogleModule->getConfig('Secret')
181: );
182: }
183: }
184: }
185: }
186:
187: public function onGetAccessToken($aArgs, &$mResult)
188: {
189: if (isset($aArgs['Service']) && $aArgs['Service'] === $this->sService && isset($aArgs['Account'])) {
190: $mResult = false;
191: $oAccount = $aArgs['Account'];
192: $oTokenData = \json_decode($oAccount->AccessToken);
193: if ($oTokenData) {
194: $iCreated = (int) $oTokenData->created;
195: $iExpiresIn = (int) $oTokenData->expires_in;
196: if (time() > ($iCreated + $iExpiresIn) && isset($oAccount->RefreshToken)) {
197: $oGoogleModule = \Aurora\System\Api::GetModule('Google');
198: if ($oGoogleModule) {
199: $oConnector = new Classes\Connector($this);
200: $aResult = $oConnector->RefreshAccessToken(
201: $oGoogleModule->getConfig('Id'),
202: $oGoogleModule->getConfig('Secret'),
203: $oAccount->RefreshToken
204: );
205: if (isset($aResult['access_token'])) {
206: $oTokenData->access_token = $aResult['access_token'];
207: $oTokenData->created = time();
208: $oTokenData->expires_in = $aResult['expires_in'];
209:
210: $mResult = $oTokenData->access_token;
211:
212: $oAccount->AccessToken = \json_encode($oTokenData);
213: $oAccount->Save();
214: }
215: }
216: } else {
217: $mResult = $oTokenData->access_token;
218: }
219: }
220:
221: return true;
222: }
223: }
224: }
225: