1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
oauth.php
См. документацию.
1<?php
2
3namespace Bitrix\Mail\Helper;
4
5use Bitrix\Main;
6use Bitrix\Mail;
7use Bitrix\Main\Web\Uri;
8use Bitrix\Mail\Helper\OAuth\UserData;
9
10
11abstract class OAuth
12{
13
17 protected $oauthEntity;
18
19 protected $service, $storedUid;
20
21 public const WEB_TYPE = 'web';
22 public const MOBILE_TYPE = 'mobile';
24
30 public static function getKnownServices()
31 {
32 static $knownServices;
33
34 if (is_null($knownServices))
35 {
36 $knownServices = [
42 ];
43 }
44
45 return $knownServices;
46 }
47
54 public static function getInstance($service = null): bool|OAuth
55 {
56 if (get_called_class() != get_class())
57 {
58 $className = get_called_class();
59 $service = $className::getServiceName();
60 }
61 else
62 {
63 if (!in_array($service, self::getKnownServices()))
64 {
65 return false;
66 }
67
68 $className = sprintf('%s\OAuth\%s', __NAMESPACE__, $service);
69 }
70
71 if (!Main\Loader::includeModule('socialservices'))
72 {
73 return false;
74 }
75
76 $instance = new $className;
77
78 $instance->service = $service;
79 $instance->storedUid = sprintf('%x%x', time(), rand(0, 0xffffffff));
80
81 if (!$instance->check())
82 {
83 return false;
84 }
85
86 return $instance;
87 }
88
95 public static function getInstanceByMeta($meta)
96 {
97 if ($meta = static::parseMeta($meta))
98 {
99 if ($instance = self::getInstance($meta['service']))
100 {
101 if ('oauthb' == $meta['type'])
102 {
103 $instance->storedUid = $meta['key'];
104 }
105
106 return $instance;
107 }
108 }
109 }
110
117 public function buildMeta()
118 {
119 return sprintf(
120 "\x00oauthb\x00%s\x00%s",
121 $this->getServiceName(),
122 $this->getStoredUid()
123 );
124 }
125
132 public static function parseMeta($meta)
133 {
134 $regex = sprintf(
135 '/^\x00(oauthb)\x00(%s)\x00([a-f0-9]+)$/',
136 join(
137 '|',
138 array_map(
139 function ($item)
140 {
141 return preg_quote($item, '/');
142 },
143 self::getKnownServices()
144 )
145 )
146 );
147
148 if (!preg_match($regex, $meta, $matches))
149 {
150 if (!preg_match('/^\x00(oauth)\x00(google|liveid)\x00(\d+)$/', $meta, $matches))
151 {
152 return null;
153 }
154 }
155
156 return array(
157 'type' => $matches[1],
158 'service' => $matches[2],
159 'key' => $matches[3],
160 );
161 }
162
170 private static function getSocservToken($service, $key)
171 {
172 if (Main\Loader::includeModule('socialservices'))
173 {
174 switch ($service)
175 {
176 case 'google':
177 $oauthClient = new \CSocServGoogleOAuth($key);
178 $oauthClient->getEntityOAuth()->addScope('https://mail.google.com/');
179 break;
180 case 'liveid':
181 $oauthClient = new \CSocServLiveIDOAuth($key);
182 $oauthClient->getEntityOAuth()->addScope(['wl.imap', 'wl.offline_access']);
183 break;
184 }
185
186 if (!empty($oauthClient))
187 {
188 return $oauthClient->getStorageToken() ?: false;
189 }
190 }
191
192 return null;
193 }
194
203 public static function getTokenByMeta($meta, int $expireGapSeconds = 10)
204 {
205 if ($meta = static::parseMeta($meta))
206 {
207 if ('oauthb' == $meta['type'])
208 {
209 if ($oauthHelper = self::getInstance($meta['service']))
210 {
211 return $oauthHelper->getStoredToken($meta['key'], $expireGapSeconds) ?: false;
212 }
213 }
214 else if ('oauth' == $meta['type'])
215 {
216 return self::getSocservToken($meta['service'], $meta['key']);
217 }
218 }
219 }
220
228 public static function getUserDataByMeta($meta, $secure = true)
229 {
230 if ($meta = static::parseMeta($meta))
231 {
232 if ($oauthHelper = self::getInstance($meta['service']))
233 {
234 if ('oauthb' == $meta['type'])
235 {
236 $oauthHelper->getStoredToken($meta['key']);
237 }
238 else if ('oauth' == $meta['type'])
239 {
240 if ($token = self::getSocservToken($meta['service'], $meta['key']))
241 {
242 $oauthHelper->getOAuthEntity()->setToken($token);
243 }
244 }
245
246 return $oauthHelper->getUserData($secure);
247 }
248 }
249
250 return null;
251 }
252
258 public function getOAuthEntity()
259 {
260 return $this->oauthEntity;
261 }
262
268 public function getStoredUid()
269 {
270 return $this->storedUid;
271 }
272
279 public function getRedirect(bool $final = true): string
280 {
281 if (isModuleInstalled('bitrix24') && defined('BX24_HOST_NAME') && !$final)
282 {
283 return $this->getControllerUrl() . '/redirect.php';
284 }
285 else
286 {
287 $uri = new Uri(Main\Engine\UrlManager::getInstance()->getHostUrl().'/bitrix/tools/mail_oauth.php');
288 return $uri->getLocator();
289 }
290 }
291
297 public function getUrl(): string
298 {
299 global $APPLICATION;
300
301 if (isModuleInstalled('bitrix24') && defined('BX24_HOST_NAME'))
302 {
303 $state = sprintf(
304 '%s?%s',
305 $this->getRedirect(),
306 http_build_query(array(
307 'check_key' => \CSocServAuthManager::getUniqueKey(),
308 'state' => rawurlencode(http_build_query(array(
309 'service' => $this->service,
310 'uid' => $this->storedUid,
311 ))),
312 ))
313 );
314 }
315 else
316 {
317 $state = http_build_query(array(
318 'check_key' => \CSocServAuthManager::getUniqueKey(),
319 'service' => $this->service,
320 'uid' => $this->storedUid,
321 ));
322 }
323
324 return $this->oauthEntity->getAuthUrl($this->getRedirect(false), $state);
325 }
326
332 protected function fetchStoredToken()
333 {
335 'filter' => array(
336 '=UID' => $this->storedUid,
337 ),
338 'order' => array(
339 'ID' => 'DESC',
340 ),
341 ))->fetch();
342 }
343
352 public function getStoredToken($uid = null, int $expireGapSeconds = 10)
353 {
354 $token = null;
355
356 if (!empty($uid))
357 {
358 $this->storedUid = $uid;
359 }
360
361 $item = $this->fetchStoredToken();
362
363 if (!empty($item))
364 {
365 $this->oauthEntity->setToken($token = $item['TOKEN']);
366 $this->oauthEntity->setRefreshToken($item['REFRESH_TOKEN']);
367 $this->oauthEntity->setAccessTokenExpires((int)($item['TOKEN_EXPIRES'] ?? 0));
368 $expireThreshold = time() + $expireGapSeconds;
369
370 if (empty($token) || $item['TOKEN_EXPIRES'] > 0 && $item['TOKEN_EXPIRES'] < $expireThreshold)
371 {
372 $this->oauthEntity->setToken(null);
373
374 if (!empty($item['REFRESH_TOKEN']))
375 {
376 if ($this->oauthEntity->getNewAccessToken($item['REFRESH_TOKEN']))
377 {
378 $tokenData = $this->oauthEntity->getTokenData();
379
381 $item['ID'],
382 array(
383 'TOKEN' => $tokenData['access_token'],
384 'REFRESH_TOKEN' => $tokenData['refresh_token'],
385 'TOKEN_EXPIRES' => $tokenData['expires_in'],
386 )
387 );
388 }
389 }
390
391 $token = $this->oauthEntity->getToken();
392 }
393 }
394
395 return $token;
396 }
397
404 public function getAccessToken($code = null)
405 {
406 if ($code)
407 {
408 $this->oauthEntity->setCode($code);
409 }
410
411 $oauthData = $_SESSION['OAUTH_DATA'];
412
413 $result = $this->oauthEntity->getAccessToken($this->getRedirect(false));
414
415 $_SESSION['OAUTH_DATA'] = $oauthData;
416
417 return $result;
418 }
419
426 public function getUserData($secure = true)
427 {
428 try
429 {
430 $userData = $this->oauthEntity->getCurrentUser();
431 }
432 catch (Main\SystemException $e)
433 {
434 }
435
436 if (!empty($userData))
437 {
438 return array_merge(
439 $this->mapUserData($userData),
440 $secure ? array() : array('__data' => $userData)
441 );
442 }
443 }
444
451 abstract protected function mapUserData(array $userData);
452
459 public static function getServiceName()
460 {
461 throw new Main\ObjectException('abstract');
462 }
463
471 public static function convertTokenExpiresToUnixtimeIfNeed(int $intervalOrTime): int
472 {
473 $year = 60 * 60 * 24 * 365;
474 $maxExpectedLifetime = 5 * $year;
475 $isInterval = $intervalOrTime <= $maxExpectedLifetime;
476
477 return $isInterval ? $intervalOrTime + time() : $intervalOrTime;
478 }
479
480 public function saveResponse($state): bool
481 {
482 $this->storedUid = $state['uid'];
483
484 if ($item = $this->fetchStoredToken())
485 {
486 $this->oauthEntity->setRefreshToken($item['REFRESH_TOKEN']);
487 }
488
489 if (!empty($_REQUEST['code']) && \CSocServAuthManager::checkUniqueKey())
490 {
491 $this->getAccessToken($_REQUEST['code']);
492
493 if ($userData = $this->getUserData(false))
494 {
495 $fields = [
496 'UID' => $this->getStoredUid(),
497 'TOKEN' => $userData['__data']['access_token'],
498 'REFRESH_TOKEN' => $userData['__data']['refresh_token'],
499 'TOKEN_EXPIRES' => $userData['__data']['expires_in'],
500 ];
501
502 if (empty($item))
503 {
505 }
506 else
507 {
509 }
510
511 $userDataObject = new UserData(
512 (string) $userData['email'],
513 (string) $userData['first_name'],
514 (string) $userData['last_name'],
515 (string) $userData['full_name'],
516 (string) $userData['image']
517 );
518
519 if (isset($userData['__data']['emailIsIntended']))
520 {
521 $userDataObject->setEmailIsIntended((bool)$userData['__data']['emailIsIntended']);
522 }
523 else
524 {
525 $userDataObject->setEmailIsIntended(false);
526 }
527
528 if (isset($userData['__data']['userPrincipalName']))
529 {
530 $userDataObject->setUserPrincipalName((string)$userData['__data']['userPrincipalName']);
531 }
532
533 $this->setPublicUserData($userDataObject);
534
535 return true;
536 }
537 }
538
539 return false;
540 }
541
542 protected function setPublicUserData(UserData $userData): void
543 {
544 $this->publicUserData = $userData;
545 }
546
547 public function getPublicUserData(): UserData
548 {
549 return $this->publicUserData;
550 }
551
558 public function handleResponse(array $state, $context = self::WEB_TYPE): void
559 {
560 if ($this->saveResponse($state))
561 {
562 if ($context === self::WEB_TYPE)
563 {
564 ?>
565
566 <script>
567
568 targetWindow = window.opener ? window.opener : window;
569
570 targetWindow.BX.onCustomEvent(
571 'OnMailOAuthBCompleted',
572 [
573 '<?=\CUtil::jsEscape($this->getStoredUid()) ?>',
574 '<?=\CUtil::jsEscape($this->getUrl()) ?>',
575 <?=$this->getPublicUserData()->getJson() ?>
576 ]
577 );
578
579 if (targetWindow !== window)
580 {
581 window.close();
582 }
583
584 </script>
585
586 <?
587 }
588 else if ($context === self::MOBILE_TYPE)
589 {
590 $params = http_build_query([
591 'storedUid' => \CUtil::jsEscape($this->getStoredUid()),
592 'email' => $this->getPublicUserData()->getEmail(),
593 ]);
594 header('Location: bitrix24://?'.$params);
595 }
596 }
597 }
598}
global $APPLICATION
Определения include.php:80
static getServiceName()
Определения google.php:40
static getServiceName()
Определения liveid.php:41
static getServiceName()
Определения mailru.php:43
static getServiceName()
Определения office365.php:43
static getServiceName()
Определения yandex.php:35
static getServiceName()
Определения oauth.php:459
getStoredToken($uid=null, int $expireGapSeconds=10)
Определения oauth.php:352
static getInstanceByMeta($meta)
Определения oauth.php:95
getRedirect(bool $final=true)
Определения oauth.php:279
static getTokenByMeta($meta, int $expireGapSeconds=10)
Определения oauth.php:203
mapUserData(array $userData)
UserData $publicUserData
Определения oauth.php:23
handleResponse(array $state, $context=self::WEB_TYPE)
Определения oauth.php:558
saveResponse($state)
Определения oauth.php:480
static getUserDataByMeta($meta, $secure=true)
Определения oauth.php:228
getStoredUid()
Определения oauth.php:268
getAccessToken($code=null)
Определения oauth.php:404
const WEB_TYPE
Определения oauth.php:21
setPublicUserData(UserData $userData)
Определения oauth.php:542
getUserData($secure=true)
Определения oauth.php:426
fetchStoredToken()
Определения oauth.php:332
const MOBILE_TYPE
Определения oauth.php:22
static getKnownServices()
Определения oauth.php:30
getOAuthEntity()
Определения oauth.php:258
$service
Определения oauth.php:19
static parseMeta($meta)
Определения oauth.php:132
getUrl()
Определения oauth.php:297
$storedUid
Определения oauth.php:19
$oauthEntity
Определения oauth.php:17
static getInstance($service=null)
Определения oauth.php:54
buildMeta()
Определения oauth.php:117
static convertTokenExpiresToUnixtimeIfNeed(int $intervalOrTime)
Определения oauth.php:471
getPublicUserData()
Определения oauth.php:547
static getList(array $parameters=array())
Определения datamanager.php:431
static add(array $data)
Определения datamanager.php:877
static update($primary, array $data)
Определения datamanager.php:1256
Определения uri.php:17
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$_REQUEST["admin_mnu_menu_id"]
Определения get_menu.php:8
$result
Определения get_property_values.php:14
$uid
Определения hot_keys_act.php:8
$context
Определения csv_new_setup.php:223
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
if(file_exists($_SERVER['DOCUMENT_ROOT'] . "/urlrewrite.php")) $uri
Определения urlrewrite.php:61
Определения action.php:3
$service
Определения payment.php:18
$year
Определения payment.php:9
$instance
Определения ps_b24_final.php:14
if(empty($signedUserToken)) $key
Определения quickway.php:257
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$matches
Определения index.php:22
$fields
Определения yandex_run.php:501