Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
oauth.php
1<?php
2
3namespace Bitrix\Mail\Helper;
4
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 = [
37 OAuth\Google::getServiceName(),
38 OAuth\LiveId::getServiceName(),
39 OAuth\Yandex::getServiceName(),
40 OAuth\Mailru::getServiceName(),
41 OAuth\Office365::getServiceName(),
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 'dummy' => 'https://dummy.bitrix24.com/',
309 'state' => rawurlencode(http_build_query(array(
310 'service' => $this->service,
311 'uid' => $this->storedUid,
312 ))),
313 ))
314 );
315 }
316 else
317 {
318 $state = http_build_query(array(
319 'check_key' => \CSocServAuthManager::getUniqueKey(),
320 'service' => $this->service,
321 'uid' => $this->storedUid,
322 ));
323 }
324
325 return $this->oauthEntity->getAuthUrl($this->getRedirect(false), $state);
326 }
327
333 protected function fetchStoredToken()
334 {
335 return Mail\Internals\OAuthTable::getList(array(
336 'filter' => array(
337 '=UID' => $this->storedUid,
338 ),
339 'order' => array(
340 'ID' => 'DESC',
341 ),
342 ))->fetch();
343 }
344
353 public function getStoredToken($uid = null, int $expireGapSeconds = 10)
354 {
355 $token = null;
356
357 if (!empty($uid))
358 {
359 $this->storedUid = $uid;
360 }
361
362 $item = $this->fetchStoredToken();
363
364 if (!empty($item))
365 {
366 $this->oauthEntity->setToken($token = $item['TOKEN']);
367 $this->oauthEntity->setRefreshToken($item['REFRESH_TOKEN']);
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
380 Mail\Internals\OAuthTable::update(
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
464 public function saveResponse($state): bool
465 {
466 $this->storedUid = $state['uid'];
467
468 if ($item = $this->fetchStoredToken())
469 {
470 $this->oauthEntity->setRefreshToken($item['REFRESH_TOKEN']);
471 }
472
473 if (!empty($_REQUEST['code']) && \CSocServAuthManager::checkUniqueKey())
474 {
475 $this->getAccessToken($_REQUEST['code']);
476
477 if ($userData = $this->getUserData(false))
478 {
479 $fields = [
480 'UID' => $this->getStoredUid(),
481 'TOKEN' => $userData['__data']['access_token'],
482 'REFRESH_TOKEN' => $userData['__data']['refresh_token'],
483 'TOKEN_EXPIRES' => $userData['__data']['expires_in'],
484 ];
485
486 if (empty($item))
487 {
488 Mail\Internals\OAuthTable::add($fields);
489 }
490 else
491 {
492 Mail\Internals\OAuthTable::update($item['ID'], $fields);
493 }
494
495 $userDataObject = new UserData(
496 (string) $userData['email'],
497 (string) $userData['first_name'],
498 (string) $userData['last_name'],
499 (string) $userData['full_name'],
500 (string) $userData['image']
501 );
502
503 if (isset($userData['__data']['emailIsIntended']))
504 {
505 $userDataObject->setEmailIsIntended((bool)$userData['__data']['emailIsIntended']);
506 }
507 else
508 {
509 $userDataObject->setEmailIsIntended(false);
510 }
511
512 if (isset($userData['__data']['userPrincipalName']))
513 {
514 $userDataObject->setUserPrincipalName((string)$userData['__data']['userPrincipalName']);
515 }
516
517 $this->setPublicUserData($userDataObject);
518
519 return true;
520 }
521 }
522
523 return false;
524 }
525
526 protected function setPublicUserData(UserData $userData): void
527 {
528 $this->publicUserData = $userData;
529 }
530
531 public function getPublicUserData(): UserData
532 {
533 return $this->publicUserData;
534 }
535
542 public function handleResponse(array $state, $context = self::WEB_TYPE): void
543 {
544 if ($this->saveResponse($state))
545 {
546 if ($context === self::WEB_TYPE)
547 {
548 ?>
549
550 <script type="text/javascript">
551
552 targetWindow = window.opener ? window.opener : window;
553
554 targetWindow.BX.onCustomEvent(
555 'OnMailOAuthBCompleted',
556 [
557 '<?=\CUtil::jsEscape($this->getStoredUid()) ?>',
558 '<?=\CUtil::jsEscape($this->getUrl()) ?>',
559 <?=$this->getPublicUserData()->getJson() ?>
560 ]
561 );
562
563 if (targetWindow !== window)
564 {
565 window.close();
566 }
567
568 </script>
569
570 <?
571 }
572 else if ($context === self::MOBILE_TYPE)
573 {
574 $params = http_build_query([
575 'storedUid' => \CUtil::jsEscape($this->getStoredUid()),
576 'email' => $this->getPublicUserData()->getEmail(),
577 ]);
578 header('Location: bitrix24://?'.$params);
579 }
580 }
581 }
582}
getStoredToken($uid=null, int $expireGapSeconds=10)
Definition oauth.php:353
static getInstanceByMeta($meta)
Definition oauth.php:95
getRedirect(bool $final=true)
Definition oauth.php:279
static getTokenByMeta($meta, int $expireGapSeconds=10)
Definition oauth.php:203
mapUserData(array $userData)
UserData $publicUserData
Definition oauth.php:23
handleResponse(array $state, $context=self::WEB_TYPE)
Definition oauth.php:542
static getUserDataByMeta($meta, $secure=true)
Definition oauth.php:228
getAccessToken($code=null)
Definition oauth.php:404
setPublicUserData(UserData $userData)
Definition oauth.php:526
getUserData($secure=true)
Definition oauth.php:426
static getKnownServices()
Definition oauth.php:30
static parseMeta($meta)
Definition oauth.php:132
static getInstance($service=null)
Definition oauth.php:54