_oConfig->sBaseUrl)
return;
$sAccessToken = BxDolSession::getInstance()->getValue('cidaascon_access_token');
$sIdToken = BxDolSession::getInstance()->getValue('cidaascon_id_token');
if (!$sAccessToken && !$sIdToken)
return;
$aParams = [];
if ($this->_oConfig->sClientID)
$aParams['client_id'] = $this->_oConfig->sClientID;
$sEndSession = $this->_oConfig->sBaseUrl . '/session/end_session';
if ($aParams)
$sEndSession .= '?' . http_build_query($aParams);
bx_logout(false);
require_once(BX_DIRECTORY_PATH_INC . 'design.inc.php');
$sIframe = '';
$sJs = '';
$oTemplate = BxDolTemplate::getInstance();
$oTemplate->setPageNameIndex(BX_PAGE_TRANSITION);
$oTemplate->setPageHeader(_t('_Please Wait'));
$oTemplate->setPageContent('page_main_code', MsgBox(_t('_Please Wait')) . $sIframe . $sJs);
// Keep the 1s meta-refresh on this page from navigating away before the iframe request is sent.
$oTemplate->setPageContent('url_relocate', '');
send_headers_page_changed();
$oTemplate->getPageCode();
exit;
/*
$sAccessToken = BxDolSession::getInstance()->getUnsetValue('cidaascon_access_token');
$sIdToken = BxDolSession::getInstance()->getUnsetValue('cidaascon_id_token');
if (!$sAccessToken)
return;
try {
$this->_getProvider()->logout($sAccessToken)->wait();
} catch (Exception $oException) {
bx_log('bx_cidaas', $this->_getExceptionMessage($oException));
}
*/
}
/**
* Redirect to Cidaas hosted login page.
*
* @return n/a - redirect or HTML page in case of error
*/
function actionStart()
{
if (isset($_GET['error'])) {
$this->_oTemplate->getPage(_t($this->_oConfig->sDefaultTitleLangKey), DesignBoxContent(_t($this->_oConfig->sDefaultTitleLangKey), MsgBox(bx_get('error'))));
exit;
}
if (isLogged()) {
$this->_redirect($this->_oConfig->sDefaultRedirectUrl);
}
if (!$this->_oConfig->sBaseUrl || !$this->_oConfig->sClientID || (!$this->_oConfig->bPkce && !$this->_oConfig->sSecret)) {
require_once(BX_DIRECTORY_PATH_INC . 'design.inc.php');
bx_import('BxDolLanguages');
$sCode = MsgBox(_t('_bx_cidaascon_profile_error_api_keys'));
$this->_oTemplate->getPage(_t('_bx_cidaascon'), $sCode);
return;
}
try {
$this->_getProvider()->loginWithBrowser($this->_oConfig->sScope, [
'state' => $this->_genToken(),
], $this->_oConfig->bPkce);
} catch (Exception $oException) {
require_once(BX_DIRECTORY_PATH_INC . 'design.inc.php');
$this->_oTemplate->getPage(_t('_Error'), MsgBox($this->_getExceptionMessage($oException)));
return;
}
// SDK stores the PKCE verifier in PHP $_SESSION; persist it in UNA session for the callback.
if ($this->_oConfig->bPkce && !empty($_SESSION['code-verifier']))
BxDolSession::getInstance()->setValue($this->_oConfig->sSessionCodeVerifier, $_SESSION['code-verifier']);
exit;
}
/**
* $aAuthData = [
* [access_token] => eyJhbGciOiJSUz...
* [id_token] => eyJhbGciOiJS...
* [state] => TkkLRS6wp4ukNyEzPhZi
* [expires_in] => 86400
* [id_token_expires_in] => 86400
* [token_type] => Bearer
* [sub] => 21xxxxxx-9da8-4fd9-ad14-e5f3c615f55a
* [sid] => c5xxxxxx-a54a-403e-b237-99c728059cc6
* [identity_id] => 74e3bf36-d1d7-4e4c-a95b-5822abfc6b97
* ]
* @return void
*/
function actionHandle()
{
require_once(BX_DIRECTORY_PATH_INC . 'design.inc.php');
try {
$oProvider = $this->_getProvider();
} catch (Exception $oException) {
$this->_oTemplate->getPage(_t('_Error'), MsgBox($this->_getExceptionMessage($oException)));
return;
}
$aParameters = $oProvider->loginCallback();
if ($this->_getToken() != ($aParameters['state'] ?? '')) {
$this->_oTemplate->getPage(_t('_Error'), MsgBox(_t('_sys_connect_state_invalid')));
return;
}
$sCode = $aParameters['code'] ?? '';
if (!$sCode || !empty($aParameters['error'])) {
$sErrorDescription = !empty($aParameters['error_description']) ? $aParameters['error_description'] : (!empty($aParameters['error']) ? $aParameters['error'] : _t('_error occured'));
$this->_oTemplate->getPage(_t('_Error'), MsgBox($sErrorDescription));
return;
}
if ($this->_oConfig->bPkce) {
$sCodeVerifier = BxDolSession::getInstance()->getUnsetValue($this->_oConfig->sSessionCodeVerifier);
if ($sCodeVerifier)
$_SESSION['code-verifier'] = $sCodeVerifier;
}
try {
$aAuthData = $oProvider->getAccessToken(GrantType::AuthorizationCode, $sCode, '', $this->_oConfig->bPkce)->wait();
// echoDbgLog($aAuthData);
if (empty($aAuthData['access_token'])) {
$sErrorDescription = isset($aAuthData['error_description']) ? $aAuthData['error_description'] : _t('_error occured');
$this->_oTemplate->getPage(_t('_Error'), MsgBox($sErrorDescription));
return;
}
BxDolSession::getInstance()->setValue('cidaascon_access_token', $aAuthData['access_token']);
BxDolSession::getInstance()->setValue('cidaascon_id_token', $aAuthData['id_token']);
$aRemoteProfileInfo = $oProvider->getUserProfile($aAuthData['access_token'])->wait();
} catch (Exception $oException) {
$this->_oTemplate->getPage(_t('_Error'), MsgBox($this->_getExceptionMessage($oException)));
return;
}
if (isset($aRemoteProfileInfo['data']) && is_array($aRemoteProfileInfo['data']))
$aRemoteProfileInfo = $aRemoteProfileInfo['data'];
if (empty($aRemoteProfileInfo['id']) && !empty($aRemoteProfileInfo['sub']))
$aRemoteProfileInfo['id'] = $aRemoteProfileInfo['sub'];
if ($aRemoteProfileInfo && !empty($aRemoteProfileInfo['id'])) {
$iLocalProfileId = $this->_oDb->getProfileId($aRemoteProfileInfo['id']);
if ($iLocalProfileId && $oProfile = BxDolProfile::getInstance($iLocalProfileId)) {
$this->setLogged($oProfile->id(), '', true, true);
}
else {
$this->_createProfile($aRemoteProfileInfo);
}
}
else {
$this->_oTemplate->getPage(_t('_Error'), MsgBox(_t('_sys_connect_profile_error_info')));
}
}
public function serviceGetSafeServices()
{
return array_merge(parent::serviceGetSafeServices(), [
'Handle' => '',
]);
}
public function serviceHandle($aRemoteProfileInfo = [])
{
if (!$this->_bIsApi)
return;
if (is_string($aRemoteProfileInfo))
$aRemoteProfileInfo = bx_api_get_browse_params($aRemoteProfileInfo);
if (empty($aRemoteProfileInfo) || !is_array($aRemoteProfileInfo))
return [
bx_api_get_msg(_t('_sys_connect_profile_error_info'))
];
if (empty($aRemoteProfileInfo['id']) && !empty($aRemoteProfileInfo['sub']))
$aRemoteProfileInfo['id'] = $aRemoteProfileInfo['sub'];
$iProfileId = $this->_oDb->getProfileId($aRemoteProfileInfo['id']);
if ($iProfileId && $oProfile = BxDolProfile::getInstance($iProfileId))
return $this->setLogged($oProfile->id());
else
return $this->_createProfile($aRemoteProfileInfo);
}
/**
*
* (
* [last_used_identity_id] => 74e3bf36-d1d7-4e4c-a95b-5822abfc6b97
* [sub] => 21e029a8-9da8-4fd9-ad14-e5f3c615f55a
* [updated_at] => 1787238995
* [createdTime] => 2026-08-20T15:16:35.513Z
* [userStatus] => VERIFIED
* [lastLoggedInTime] => 2026-08-24T10:05:34.3Z
* [customFields] => Array
* (
* [city] => Sydney
* [department] => Support
* [job_title] => Support
* [name_of_company] => UNA Inc
* [other_interests] => IT
* [responsibilty] => Support
* )
*
* [email] => team@unacms.com
* [email_verified] => 1
* [provider] => self
* [given_name] => UNA
* [family_name] => Team
* [address] => Array
* (
* [country] => Australia
* )
*
* [user_status] => VERIFIED
* [name] => UNA Team
* [last_accessed_at] => 1787565934
* )
*
* @param $aProfileInfo - remote profile info
* @param $sAlternativeName - suffix to add to NickName to make it unique
* @return profile array info, ready for the local database
*/
protected function _convertRemoteFields($aProfileInfo, $sAlternativeName = '')
{
$aProfileFields = $aProfileInfo;
$sEmail = !empty($aProfileInfo['email']) ? $aProfileInfo['email'] : '';
if (!$sEmail && !empty($aProfileInfo['identities'][0]['email']))
$sEmail = $aProfileInfo['identities'][0]['email'];
$sName = !empty($aProfileInfo['preferred_username']) ? $aProfileInfo['preferred_username'] : '';
if (!$sName && !empty($aProfileInfo['name']))
$sName = $aProfileInfo['name'];
if (!$sName && !empty($aProfileInfo['given_name']))
$sName = $aProfileInfo['given_name'];
if (!$sName && $sEmail)
$sName = explode('@', $sEmail)[0];
if (!$sName)
$sName = !empty($aProfileInfo['sub']) ? $aProfileInfo['sub'] : '';
$sFullname = !empty($aProfileInfo['name']) ? $aProfileInfo['name'] : trim((!empty($aProfileInfo['given_name']) ? $aProfileInfo['given_name'] : '') . ' ' . (!empty($aProfileInfo['family_name']) ? $aProfileInfo['family_name'] : ''));
if (!$sFullname)
$sFullname = $sName;
$aProfileFields['name'] = $sName;
$aProfileFields['fullname'] = $sFullname;
$aProfileFields['first_name'] = !empty($aProfileInfo['given_name']) ? $aProfileInfo['given_name'] : '';
$aProfileFields['last_name'] = !empty($aProfileInfo['family_name']) ? $aProfileInfo['family_name'] : '';
$aProfileFields['email'] = $sEmail;
$aProfileFields['picture'] = !empty($aProfileInfo['picture']) ? $aProfileInfo['picture'] : '';
$aProfileFields['allow_view_to'] = getParam('bx_cidaascon_privacy');
return $aProfileFields;
}
/**
* @return BxCidaasConProvider
*/
protected function _getProvider()
{
bx_import('Provider', $this->_aModule);
return new BxCidaasConProvider(
$this->_oConfig->sBaseUrl,
$this->_oConfig->sClientID,
$this->_oConfig->sSecret ? $this->_oConfig->sSecret : '',
$this->_oConfig->sPageHandle,
null,
$this->_oConfig->bDebug
);
}
protected function _getExceptionMessage($oException)
{
if ($oException instanceof ClientException && $oException->hasResponse()) {
$aBody = json_decode((string)$oException->getResponse()->getBody(), true);
if (!empty($aBody['error']['error_description']))
return $aBody['error']['error_description'];
if (!empty($aBody['error_description']))
return $aBody['error_description'];
if (!empty($aBody['error']) && is_string($aBody['error']))
return $aBody['error'];
}
$sMessage = $oException->getMessage();
return $sMessage ? $sMessage : _t('_error occured');
}
}
/** @} */