diff --git a/main/inc/lib/online.inc.php b/main/inc/lib/online.inc.php index c714e63aea..241ae04d23 100755 --- a/main/inc/lib/online.inc.php +++ b/main/inc/lib/online.inc.php @@ -166,10 +166,12 @@ function online_logout($user_id = null, $logout_redirect = false) $url = api_get_path(WEB_PATH).'index.php'; if ($logout_redirect && api_get_plugin_setting('azure_active_directory', 'enable') == 'true') { - $activeDirectoryPlugin = AzureActiveDirectory::create(); - $azureLogout = $activeDirectoryPlugin->getUrl(AzureActiveDirectory::URL_TYPE_SIGNOUT); - if (!empty($azureLogout)) { - $url = $azureLogout; + if (ChamiloSession::read('_user_auth_source') === 'azure_active_directory') { + $activeDirectoryPlugin = AzureActiveDirectory::create(); + $azureLogout = $activeDirectoryPlugin->getUrl(AzureActiveDirectory::URL_TYPE_LOGOUT); + if (!empty($azureLogout)) { + $url = $azureLogout; + } } } diff --git a/plugin/azure_active_directory/index.php b/plugin/azure_active_directory/index.php index 9d5be844c6..0fb4d78e45 100644 --- a/plugin/azure_active_directory/index.php +++ b/plugin/azure_active_directory/index.php @@ -10,23 +10,7 @@ $activeDirectoryPlugin = AzureActiveDirectory::create(); if ($activeDirectoryPlugin->get(AzureActiveDirectory::SETTING_ENABLE) === 'true') { - $signUp = $activeDirectoryPlugin->get(AzureActiveDirectory::SETTING_SIGNIN_POLICY); - $signIn = $activeDirectoryPlugin->get(AzureActiveDirectory::SETTING_SIGNUP_POLICY); - $signUnified = $activeDirectoryPlugin->get(AzureActiveDirectory::SETTING_SIGNUNIFIED_POLICY); - $_template['block_title'] = $activeDirectoryPlugin->get(AzureActiveDirectory::SETTING_BLOCK_NAME); - if ($signUp) { - $_template['signup_url'] = $activeDirectoryPlugin->getUrl(AzureActiveDirectory::URL_TYPE_SIGNUP); - } - - if ($signIn) { - $_template['signin_url'] = $activeDirectoryPlugin->getUrl(AzureActiveDirectory::URL_TYPE_SIGNIN); - } - - if ($signUnified) { - $_template['signunified_url'] = $activeDirectoryPlugin->getUrl(AzureActiveDirectory::URL_TYPE_SIGNUNIFIED); - } - - $_template['signout_url'] = $activeDirectoryPlugin->getUrl(AzureActiveDirectory::URL_TYPE_SIGNOUT); + $_template['signin_url'] = $activeDirectoryPlugin->getUrl(AzureActiveDirectory::URL_TYPE_AUTHORIZE); } diff --git a/plugin/azure_active_directory/lang/english.php b/plugin/azure_active_directory/lang/english.php index 84675cc8c9..c393129da4 100644 --- a/plugin/azure_active_directory/lang/english.php +++ b/plugin/azure_active_directory/lang/english.php @@ -13,7 +13,7 @@ $strings['plugin_comment'] = 'Allow authentication with Microsoft\'s Azure Activ $strings['enable'] = 'Enable'; $strings['app_id'] = 'Application ID'; $strings['app_id_help'] = 'Enter the Application Id assinged to your app by the Azure portal, e.g. 580e250c-8f26-49d0-bee8-1c078add1609'; -$strings['tenant'] = 'Tenant'; +$strings['app_secret'] = 'Application secret'; $strings['tenant_help'] = 'Enter the name of your B2C directory, e.g. contoso.onmicrosoft.com'; $strings['signup_policy'] = 'Sign up policy'; $strings['signup_policy_help'] = 'Enter your sign up policy name, e.g.g b2c_1_sign_up'; diff --git a/plugin/azure_active_directory/src/AzureActiveDirectory.php b/plugin/azure_active_directory/src/AzureActiveDirectory.php index 461033b477..09535a1909 100644 --- a/plugin/azure_active_directory/src/AzureActiveDirectory.php +++ b/plugin/azure_active_directory/src/AzureActiveDirectory.php @@ -1,6 +1,8 @@ 'boolean', self::SETTING_APP_ID => 'text', - self::SETTING_TENANT => 'text', - self::SETTING_SIGNUP_POLICY => 'text', - self::SETTING_SIGNIN_POLICY => 'text', - self::SETTING_SIGNUNIFIED_POLICY => 'text', + self::SETTING_APP_SECRET => 'text', self::SETTING_BLOCK_NAME => 'text', ]; @@ -63,56 +58,34 @@ class AzureActiveDirectory extends Plugin } /** - * @param string $urlType Type of URL to generate + * @return Azure + */ + public function getProvider() + { + $provider = new Azure([ + 'clientId' => $this->get(self::SETTING_APP_ID), + 'clientSecret' => $this->get(self::SETTING_APP_SECRET), + 'redirectUri' => api_get_path(WEB_PLUGIN_PATH).'azure_active_directory/src/callback.php', + ]); + + return $provider; + } + + /** + * @param $urlType Type of URL to generate * * @return string */ public function getUrl($urlType) { - $settingsInfo = $this->get_settings(); - $settings = []; - - foreach ($settingsInfo as $settingInfo) { - $variable = str_replace($this->get_name().'_', '', $settingInfo['variable']); - $settings[$variable] = $settingInfo['selected_value']; - } - - if (isset($settings[self::SETTING_TENANT])) { - $url = "https://login.microsoftonline.com/{$settings[self::SETTING_TENANT]}/oauth2/v2.0/"; - } else { - return ''; - } - - $callback = api_get_path(WEB_PLUGIN_PATH).$this->get_name().'/src/callback.php'; - - if ($urlType === self::URL_TYPE_SIGNOUT) { - $action = 'logout'; - $urlParams = [ - 'p' => $settings[self::SETTING_SIGNIN_POLICY], - 'post_logout_redirect_uri' => $callback, - ]; - } else { - $action = 'authorize'; - $policy = $settings[self::SETTING_SIGNUP_POLICY]; - - if ($urlType === self::URL_TYPE_SIGNIN) { - $policy = $settings[self::SETTING_SIGNIN_POLICY]; - } elseif ($urlType === self::URL_TYPE_SIGNUNIFIED) { - $policy = $settings[self::SETTING_SIGNUNIFIED_POLICY]; - } + if (self::URL_TYPE_LOGOUT === $urlType) { + $provider = $this->getProvider(); - $urlParams = [ - 'client_id' => $settings[self::SETTING_APP_ID], - 'response_type' => 'id_token', - 'redirect_uri' => $callback, - 'scope' => 'openid', - 'response_mode' => 'form_post', - 'state' => time(), - 'nonce' => time(), - 'p' => $policy, - ]; + return $provider->getLogoutUrl( + api_get_path(WEB_PATH) + ); } - return $url.$action.'?'.http_build_query($urlParams); + return api_get_path(WEB_PLUGIN_PATH).$this->get_name().'/src/callback.php'; } } diff --git a/plugin/azure_active_directory/src/callback.php b/plugin/azure_active_directory/src/callback.php index ec0ce27fba..70bb97653c 100644 --- a/plugin/azure_active_directory/src/callback.php +++ b/plugin/azure_active_directory/src/callback.php @@ -2,51 +2,79 @@ /* For license terms, see /license.txt */ require __DIR__.'/../../../main/inc/global.inc.php'; -require_once __DIR__.'/../../../main/auth/external_login/functions.inc.php'; -if (isset($_POST['error']) || empty($_REQUEST)) { - header('Location: '.api_get_path(WEB_PATH).'index.php?logout=logout'); +$plugin = AzureActiveDirectory::create(); + +$provider = $plugin->getProvider(); + +if (!isset($_GET['code'])) { + // If we don't have an authorization code then get one + $authUrl = $provider->getAuthorizationUrl(); + + ChamiloSession::write('oauth2state', $provider->getState()); + + header('Location: '.$authUrl); + exit; +} + +// Check given state against previously stored one to mitigate CSRF attack +if (empty($_GET['state']) || ($_GET['state'] !== ChamiloSession::read('oauth2state'))) { + ChamiloSession::erase('oauth2state'); + + exit; +} + +// Try to get an access token (using the authorization code grant) +$token = $provider->getAccessToken('authorization_code', [ + 'code' => $_GET['code'], + 'resource' => 'https://graph.windows.net', +]); + +$me = null; + +try { + $me = $provider->get("me", $token); +} catch (Exception $e) { exit; } -list($jwtHeader, $jwtPayload, $jwtSignature) = explode('.', $_REQUEST['id_token']); - -$jwtHeader = json_decode(base64_decode($jwtHeader)); -$jwtPayload = json_decode(base64_decode($jwtPayload)); - -$u = [ - 'firstname' => $jwtPayload->given_name, - 'lastname' => $jwtPayload->family_name, - 'status' => STUDENT, - 'email' => $jwtPayload->emails[0], - 'username' => $jwtPayload->emails[0], - 'language' => 'en', - 'password' => 'azure_active_directory', - 'auth_source' => 'azure_active_directory '.$jwtPayload->idp, - 'extra' => [], -]; - -$userInfo = api_get_user_info_from_email($jwtPayload->emails[0]); - -if ($userInfo === false) { - // we have to create the user - $chamilo_uid = external_add_user($u); - - if ($chamilo_uid !== false) { - $_user['user_id'] = $chamilo_uid; - $_user['uidReset'] = true; - $_SESSION['_user'] = $_user; - } -} else { - // User already exists, update info and login - $chamilo_uid = $userInfo['user_id']; - $u['user_id'] = $chamilo_uid; - external_update_user($u); - - $_user['user_id'] = $chamilo_uid; - $_user['uidReset'] = true; - $_SESSION['_user'] = $_user; +$userInfo = []; + +if (!empty($me['email'])) { + $userInfo = api_get_user_info_from_email($me['email']); +} + +if (empty($userInfo) && !empty($me['email'])) { + $extraFieldValue = new ExtraFieldValue('user'); + $itemValue = $extraFieldValue->get_item_id_from_field_variable_and_field_value( + 'organisationemail', + $me['email'] + ); + + $userInfo = api_get_user_info($itemValue['item_id']); +} + +if (empty($userInfo) && !empty($me['mailNickname'])) { + $extraFieldValue = new ExtraFieldValue('user'); + $itemValue = $extraFieldValue->get_item_id_from_field_variable_and_field_value( + 'azure_id', + $me['mailNickname'] + ); + + $userInfo = api_get_user_info($itemValue['item_id']); } +if (empty($userInfo)) { + header('Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=user_password_incorrect'); + + exit; +} + +$_user['user_id'] = $userInfo['user_id']; +$_user['uidReset'] = true; + +ChamiloSession::write('_user', $_user); +ChamiloSession::write('_user_auth_source', 'azure_active_directory'); + header('Location: '.api_get_path(WEB_PATH)); exit; diff --git a/plugin/azure_active_directory/view/block.tpl b/plugin/azure_active_directory/view/block.tpl index ad02f1d359..38ccd1a1d0 100644 --- a/plugin/azure_active_directory/view/block.tpl +++ b/plugin/azure_active_directory/view/block.tpl @@ -4,16 +4,6 @@

{{ azure_active_directory.block_title }}

{% endif %} - {% if not azure_active_directory.signin_url is empty %} - {{ 'SignIn'|get_lang }} - {% endif %} - - {% if not azure_active_directory.signup_url is empty %} - {{ 'SignUp'|get_lang }} - {% endif %} - - {% if not azure_active_directory.signunified_url is empty %} - {{ 'SignUpAndSignIn'|get_plugin_lang('AzureActiveDirectory') }} - {% endif %} + {{ 'SignIn'|get_lang }} {% endif %}