entityOAuth) { $this->entityOAuth = new CLiveIDOAuthInterface(); } return $this->entityOAuth; } public function GetSettings() { return array( array("liveid_appid", GetMessage("socserv_liveid_client_id"), "", Array("text", 40)), array("liveid_appsecret", GetMessage("socserv_liveid_client_secret"), "", Array("text", 40)), array( 'note' => getMessage( 'socserv_liveid_form_note_3', array( '#URL#' => \CHttp::urn2uri('/bitrix/tools/oauth/liveid.php'), '#MAIL_URL#' => \CHttp::urn2uri('/bitrix/tools/mail_oauth.php'), ) ), ), ); } public function GetFormHtml($arParams) { $url = $this->getUrl('opener', null, $arParams); if($arParams["FOR_INTRANET"]) return array("ON_CLICK" => 'onclick="BX.util.popup(\''.htmlspecialcharsbx(CUtil::JSEscape($url)).'\', 580, 400)"'); return ''.GetMessage("MAIN_OPTION_COMMENT").''; } public function GetOnClickJs($arParams) { $url = $this->getUrl('opener', null, $arParams); return "BX.util.popup('".CUtil::JSEscape($url)."', 580, 400)"; } public function getUrl($location = 'opener', $addScope = null, $arParams = array()) { global $APPLICATION; if ($this->userId == null) { $this->getEntityOAuth()->setRefreshToken("skip"); } if ($addScope !== null) { $this->getEntityOAuth()->addScope($addScope); } if (IsModuleInstalled('bitrix24') && defined('BX24_HOST_NAME')) { $redirect_uri = self::CONTROLLER_URL."/redirect.php"; $state = \CHTTP::URN2URI("/bitrix/tools/oauth/liveid.php")."?state="; $backurl = urlencode($GLOBALS["APPLICATION"]->GetCurPageParam('check_key='.\CSocServAuthManager::getUniqueKey(), array("logout", "auth_service_error", "auth_service_id", "backurl"))).(isset($arParams['BACKURL']) ? '&redirect_url='.urlencode($arParams['BACKURL']) : '').'&mode='.$location; $state .= urlencode(urlencode("backurl=".$backurl)); } else { $backurl = $APPLICATION->GetCurPageParam( 'check_key='.\CSocServAuthManager::getUniqueKey(), array("logout", "auth_service_error", "auth_service_id", "backurl") ); $redirect_uri = \CHTTP::URN2URI("/bitrix/tools/oauth/liveid.php"); $state = 'site_id='.SITE_ID.'&backurl='.urlencode($backurl).(isset($arParams['BACKURL']) ? '&redirect_url='.urlencode($arParams['BACKURL']) : '').'&mode='.$location; } return $this->getEntityOAuth()->GetAuthUrl($redirect_uri, $state); } public function getStorageToken() { $accessToken = null; $userId = intval($this->userId); if($userId > 0) { $dbSocservUser = \Bitrix\Socialservices\UserTable::getList([ 'filter' => ['=USER_ID' => $userId, "=EXTERNAL_AUTH_ID" => "LiveIDOAuth"], 'select' => ["OATOKEN", "REFRESH_TOKEN", "OATOKEN_EXPIRES"] ]); if($arOauth = $dbSocservUser->fetch()) { $accessToken = $arOauth["OATOKEN"]; if(empty($accessToken) || ((intval($arOauth["OATOKEN_EXPIRES"]) > 0) && (intval($arOauth["OATOKEN_EXPIRES"] < intval(time()))))) { if(isset($arOauth['REFRESH_TOKEN'])) $this->entityOAuth->getNewAccessToken($arOauth['REFRESH_TOKEN'], $userId, true); if(($accessToken = $this->entityOAuth->getToken()) === false) return null; } } } return $accessToken; } public function Authorize() { global $APPLICATION; $APPLICATION->RestartBuffer(); $bProcessState = false; $bSuccess = SOCSERV_AUTHORISATION_ERROR; if(isset($_REQUEST["code"]) && $_REQUEST["code"] != '' && CSocServAuthManager::CheckUniqueKey()) { if(IsModuleInstalled('bitrix24') && defined('BX24_HOST_NAME')) $redirect_uri = self::CONTROLLER_URL."/redirect.php"; else $redirect_uri = \CHTTP::URN2URI("/bitrix/tools/oauth/liveid.php"); $appID = trim(self::GetOption("liveid_appid")); $appSecret = trim(self::GetOption("liveid_appsecret")); $gAuth = new CLiveIDOAuthInterface($appID, $appSecret, $_REQUEST["code"]); $bProcessState = true; if($gAuth->GetAccessToken($redirect_uri) !== false) { $arLiveIDUser = $gAuth->GetCurrentUser(); if(is_array($arLiveIDUser) && ($arLiveIDUser['id'] <> '')) { $email = $first_name = $last_name = ""; $login = "LiveID".$arLiveIDUser['id']; $uId = $arLiveIDUser['id']; if($arLiveIDUser['first_name'] <> '') $first_name = $arLiveIDUser['first_name']; if($arLiveIDUser['last_name'] <> '') $last_name = $arLiveIDUser['last_name']; if($arLiveIDUser['emails']['preferred'] <> '') { $email = $arLiveIDUser['emails']['preferred']; $login = $arLiveIDUser['emails']['preferred']; $uId = $arLiveIDUser['emails']['preferred']; } $arFields = array( 'EXTERNAL_AUTH_ID' => self::ID, 'XML_ID' => $uId, 'LOGIN' => $login, 'EMAIL' => $email, 'NAME'=> $first_name, 'LAST_NAME'=> $last_name, ); $arFields["PERSONAL_WWW"] = $arLiveIDUser["link"]; if(isset($arLiveIDUser['access_token'])) $arFields["OATOKEN"] = $arLiveIDUser['access_token']; if(isset($arLiveIDUser['refresh_token'])) $arFields["REFRESH_TOKEN"] = $arLiveIDUser['refresh_token']; if(isset($arLiveIDUser['expires_in'])) $arFields["OATOKEN_EXPIRES"] = time() + $arLiveIDUser['expires_in']; if(SITE_ID <> '') $arFields["SITE_ID"] = SITE_ID; $bSuccess = $this->AuthorizeUser($arFields); } } } if(!$bProcessState) { unset($_REQUEST["state"]); } $url = ($APPLICATION->GetCurDir() == "/login/") ? "" : $APPLICATION->GetCurDir(); $aRemove = array("logout", "auth_service_error", "auth_service_id", "code", "error_reason", "error", "error_description", "check_key", "current_fieldset"); $mode = 'opener'; $addParams = true; if(isset($_REQUEST["state"])) { $arState = array(); parse_str($_REQUEST["state"], $arState); if(isset($arState['backurl']) || isset($arState['redirect_url'])) { $url = !empty($arState['redirect_url']) ? $arState['redirect_url'] : $arState['backurl']; if(mb_substr($url, 0, 1) !== "#") { $parseUrl = parse_url($url); $urlPath = $parseUrl["path"]; $arUrlQuery = explode('&', $parseUrl["query"]); foreach($arUrlQuery as $key => $value) { foreach($aRemove as $param) { if(mb_strpos($value, $param."=") === 0) { unset($arUrlQuery[$key]); break; } } } $url = (!empty($arUrlQuery)) ? $urlPath.'?'.implode("&", $arUrlQuery) : $urlPath; } else { $addParams = false; } } if(isset($arState['mode'])) { $mode = $arState['mode']; } } if($bSuccess === SOCSERV_REGISTRATION_DENY) { $url = (preg_match("/\?/", $url)) ? $url.'&' : $url.'?'; $url .= 'auth_service_id='.self::ID.'&auth_service_error='.SOCSERV_REGISTRATION_DENY; } elseif($bSuccess !== true) { $url = (isset($parseUrl)) ? $urlPath.'?auth_service_id='.self::ID.'&auth_service_error='.$bSuccess : $APPLICATION->GetCurPageParam(('auth_service_id='.self::ID.'&auth_service_error='.$bSuccess), $aRemove); } if($addParams && CModule::IncludeModule("socialnetwork") && mb_strpos($url, "current_fieldset=") === false) $url = (preg_match("/\?/", $url)) ? $url."¤t_fieldset=SOCSERV" : $url."?current_fieldset=SOCSERV"; $url = CUtil::JSEscape($url); if($addParams) { $location = ($mode == "opener") ? 'if(window.opener) window.opener.location = \''.$url.'\'; window.close();' : ' window.location = \''.$url.'\';'; } else { //fix for chrome $location = ($mode == "opener") ? 'if(window.opener) window.opener.location = window.opener.location.href + \''.$url.'\'; window.close();' : ' window.location = window.location.href + \''.$url.'\';'; } $JSScript = ' '; echo $JSScript; CMain::FinalActions(); } public function getFriendsList($limit = 0, $offset = 0) { $li = new CLiveIDOAuthInterface(); if(IsModuleInstalled('bitrix24') && defined('BX24_HOST_NAME')) { $redirect_uri = self::CONTROLLER_URL."/redirect.php"; } else { $redirect_uri = \CHTTP::URN2URI("/bitrix/tools/oauth/liveid.php"); } if($li->GetAccessToken($redirect_uri) !== false) { $res = $li->GetCurrentUserFriends($limit, $offset); } if(is_array($res) && is_array($res['data'])) { foreach($res['data'] as $key => $contact) { $res['data'][$key]['uid'] = $contact['id']; $res['data'][$key]['url'] = $this->getProfileUrl($contact['id']); } return $res['data']; } return false; } public function getProfileUrl($id) { return 'https://people.live.com/'; } } class CLiveIDOAuthInterface { const SERVICE_ID = "LiveIDOAuth"; const AUTH_URL = "https://login.live.com/oauth20_authorize.srf"; const TOKEN_URL = "https://login.live.com/oauth20_token.srf"; const CONTACTS_URL = "https://apis.live.net/v5.0/me/"; const FRIENDS_URL = "https://apis.live.net/v5.0/me/contacts/"; protected $appID; protected $appSecret; protected $code = false; protected $access_token = false; protected $accessTokenExpires = 0; protected $refresh_token = ''; protected $scope = array( 'wl.signin', 'wl.basic', 'wl.offline_access', 'wl.emails', ); public function __construct($appID = false, $appSecret = false, $code=false) { if($appID === false) { $appID = trim(CSocServLiveIDOAuth::GetOption("liveid_appid")); } if($appSecret === false) { $appSecret = trim(CSocServLiveIDOAuth::GetOption("liveid_appsecret")); } $this->httpTimeout = SOCSERV_DEFAULT_HTTP_TIMEOUT; $this->appID = $appID; $this->appSecret = $appSecret; $this->code = $code; } public function getAccessTokenExpires() { return $this->accessTokenExpires; } public function getAppID() { return $this->appID; } public function getAppSecret() { return $this->appSecret; } public function getToken() { return $this->access_token; } /** * @param string $refresh_token */ public function setRefreshToken($refresh_token) { $this->refresh_token = $refresh_token; } public function setScope($scope) { $this->scope = $scope; } public function getScope() { return $this->scope; } public function addScope($scope) { if(is_array($scope)) $this->scope = array_merge($this->scope, $scope); else $this->scope[] = $scope; return $this; } public function getScopeEncode() { return implode('+', array_map('urlencode', array_unique($this->getScope()))); } public function GetAuthUrl($redirect_uri, $state='') { return self::AUTH_URL. "?client_id=".urlencode($this->appID). "&redirect_uri=".urlencode($redirect_uri). "&scope=".$this->getScopeEncode(). "&response_type=code". ($state <> ''? '&state='.urlencode($state):''); } public function GetAccessToken($redirect_uri) { $tokens = $this->getStorageTokens(); if(is_array($tokens)) { $this->access_token = $tokens["OATOKEN"]; $this->accessTokenExpires = $tokens["OATOKEN_EXPIRES"]; if(!$this->code) { if($this->checkAccessToken()) { return true; } elseif(isset($tokens["REFRESH_TOKEN"])) { if($this->getNewAccessToken($tokens["REFRESH_TOKEN"])) { return true; } } } $this->deleteStorageTokens(); } if($this->code === false) { return false; } $result = CHTTP::sPostHeader(self::TOKEN_URL, array( "code"=>$this->code, "client_id"=>$this->appID, "client_secret"=>$this->appSecret, "redirect_uri"=>$redirect_uri, "grant_type"=>"authorization_code", ), array(), $this->httpTimeout); $arResult = CUtil::JsObjectToPhp($result); if(isset($arResult["access_token"]) && $arResult["access_token"] <> '') { $this->access_token = $arResult["access_token"]; $this->accessTokenExpires = $arResult["expires_in"]; if(isset($arResult["refresh_token"]) && $arResult["refresh_token"] <> '') { $this->refresh_token = $arResult["refresh_token"]; } $_SESSION["OAUTH_DATA"] = array("OATOKEN" => $this->access_token); return true; } return false; } public function GetCurrentUser() { if($this->access_token === false) return false; $result = CHTTP::sGetHeader(self::CONTACTS_URL."?access_token=".urlencode($this->access_token), array(), $this->httpTimeout); if(!defined("BX_UTF")) $result = CharsetConverter::ConvertCharset($result, "utf-8", LANG_CHARSET); $result = CUtil::JsObjectToPhp($result); if(is_array($result)) { $result["access_token"] = $this->access_token; $result["refresh_token"] = $this->refresh_token; $result["expires_in"] = $this->accessTokenExpires; } return $result; } public function GetCurrentUserFriends($limit = 0, $offset = 0) { if($this->access_token === false) return false; $url = self::FRIENDS_URL."?access_token=".urlencode($this->access_token); if($limit > 0) { $url .= '&limit='.intval($limit)."&offset=".intval($offset); } $result = CHTTP::sGetHeader($url, array(), $this->httpTimeout); if(!defined("BX_UTF")) $result = CharsetConverter::ConvertCharset($result, "utf-8", LANG_CHARSET); $result = CUtil::JsObjectToPhp($result); if(is_array($result)) { $result["access_token"] = $this->access_token; $result["refresh_token"] = $this->refresh_token; $result["expires_in"] = $this->accessTokenExpires; } return $result; } private function getStorageTokens() { global $USER; if(is_object($USER)) { $dbSocservUser = \Bitrix\Socialservices\UserTable::getList([ 'filter' => ['=USER_ID' => $USER->GetID(), "=EXTERNAL_AUTH_ID" => CSocServLiveIDOAuth::ID], 'select' => ["USER_ID", "OATOKEN", "OATOKEN_EXPIRES", "REFRESH_TOKEN"] ]); return $dbSocservUser->fetch(); } return false; } private function checkAccessToken() { return (($this->access_token - 30) < time()) ? false : true; } public function getNewAccessToken($refreshToken, $userId = 0, $save = false) { if($this->appID == false || $this->appSecret == false) return false; $result = CHTTP::sPostHeader(self::TOKEN_URL, array( "refresh_token"=>$refreshToken, "client_id"=>$this->appID, "client_secret"=>$this->appSecret, "grant_type"=>"refresh_token", ), array(), $this->httpTimeout); $arResult = CUtil::JsObjectToPhp($result); if(isset($arResult["access_token"]) && $arResult["access_token"] <> '') { $this->access_token = $arResult["access_token"]; $this->accessTokenExpires = $arResult["expires_in"]; if($save && intval($userId) > 0) { $dbSocservUser = \Bitrix\Socialservices\UserTable::getList([ 'filter' => [ '=USER_ID' => intval($userId), "=EXTERNAL_AUTH_ID" => 'LiveIDOAuth' ], 'select' => ["ID"] ]); if($arOauth = $dbSocservUser->fetch()) \Bitrix\Socialservices\UserTable::update($arOauth["ID"], array("OATOKEN" => $this->access_token, "OATOKEN_EXPIRES" => time() + $this->accessTokenExpires)); } return true; } return false; } protected function deleteStorageTokens() { global $USER; if(is_object($USER) && $USER->IsAuthorized()) { $dbSocservUser = \Bitrix\Socialservices\UserTable::getList(array( 'filter' => array( '=USER_ID' => $USER->GetID(), "=EXTERNAL_AUTH_ID" => static::SERVICE_ID ), 'select' => array("ID") )); while($accessToken = $dbSocservUser->fetch()) { \Bitrix\Socialservices\UserTable::delete($accessToken['ID']); } } } } ?>