PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/main/auth/sso/sso.class.php

https://bitbucket.org/hanutimes/hanutimes
PHP | 234 lines | 148 code | 12 blank | 74 comment | 32 complexity | e7ab29a0e69479ca973179fa5e1f1cbb MD5 | raw file
  1. <?php
  2. use \ChamiloSession as Session;
  3. /* For licensing terms, see /license.txt */
  4. /**
  5. * This file contains the necessary elements to implement a Single Sign On
  6. * mechanism with an arbitrary external web application (given some light
  7. * development there) and is based on the Drupal-Chamilo module implementation.
  8. * To develop a new authentication mechanism, please extend this class and
  9. * overwrite its method, then modify the corresponding calling code in
  10. * main/inc/local.inc.php
  11. * @package chamilo.auth.sso
  12. */
  13. /**
  14. * The SSO class allows for management or remote Single Sign On resources
  15. */
  16. class sso {
  17. public $protocol; // 'http://',
  18. public $domain; // 'localhost/project/drupal5',
  19. public $auth_uri; // '/?q=user',
  20. public $deauth_uri; // '/?q=logout',
  21. public $referer; // http://my.chamilo.com/main/auth/profile.php
  22. /**
  23. * Instanciates the object, initializing all relevant URL strings
  24. */
  25. public function __construct() {
  26. $this->protocol = api_get_setting('sso_authentication_protocol');
  27. // There can be multiple domains, so make sure to take only the first
  28. // This might be later extended with a decision process
  29. $domains = split(',',api_get_setting('sso_authentication_domain'));
  30. $this->domain = trim($domains[0]);
  31. $this->auth_uri = api_get_setting('sso_authentication_auth_uri');
  32. $this->deauth_uri = api_get_setting('sso_authentication_unauth_uri');
  33. //cut the string to avoid recursive URL construction in case of failure
  34. $this->referer = $this->protocol.$_SERVER['HTTP_HOST'].substr($_SERVER['REQUEST_URI'],0,strpos($_SERVER['REQUEST_URI'],'sso'));
  35. $this->deauth_url = $this->protocol.$this->domain.$this->deauth_uri;
  36. $this->master_url = $this->protocol.$this->domain.$this->auth_uri;
  37. $this->target = api_get_path(WEB_PATH);
  38. }
  39. /**
  40. * Unlogs the user from the remote server
  41. */
  42. public function logout() {
  43. header('Location: '.$this->deauth_url);
  44. exit;
  45. }
  46. /**
  47. * Sends the user to the master URL for a check of active connection
  48. */
  49. public function ask_master() {
  50. $params = 'sso_referer='.urlencode($this->referer).'&sso_target='.urlencode($this->target);
  51. if (strpos($this->master_url, "?") === false) {
  52. $params = "?$params";
  53. } else {
  54. $params = "&$params";
  55. }
  56. header('Location: '.$this->master_url.$params);
  57. exit;
  58. }
  59. function redirect_to($sso, $user_id, $logged_in) {
  60. if (isset($sso['target']) && !empty($sso['target'])) {
  61. header('Location: '. $sso['target']);
  62. } else {
  63. //Use this handy function to deal with platform settings
  64. Redirect::session_request_uri($logged_in, $user_id);
  65. }
  66. exit;
  67. }
  68. /**
  69. * Validates the received active connection data with the database
  70. * @return bool Return the loginFailed variable value to local.inc.php
  71. */
  72. public function check_user() {
  73. global $_user;
  74. $loginFailed = false;
  75. //change the way we recover the cookie depending on how it is formed
  76. $sso = $this->decode_cookie($_GET['sso_cookie']);
  77. //error_log('check_user');
  78. //error_log('sso decode cookie: '.print_r($sso,1));
  79. //lookup the user in the main database
  80. $user_table = Database::get_main_table(TABLE_MAIN_USER);
  81. $sql = "SELECT user_id, username, password, auth_source, active, expiration_date, status
  82. FROM $user_table
  83. WHERE username = '".trim(Database::escape_string($sso['username']))."'";
  84. $result = Database::query($sql);
  85. if (Database::num_rows($result) > 0) {
  86. //error_log('user exists');
  87. $uData = Database::fetch_array($result);
  88. //Check the user's password
  89. if ($uData['auth_source'] == PLATFORM_AUTH_SOURCE) {
  90. //the authentification of this user is managed by Chamilo itself
  91. // check the user's password
  92. // password hash comes already parsed in sha1, md5 or none
  93. /*
  94. error_log($sso['secret']);
  95. error_log($uData['password']);
  96. error_log($sso['username']);
  97. error_log($uData['username']);
  98. */
  99. if ($sso['secret'] === sha1($uData['password'])
  100. && ($sso['username'] == $uData['username'])) {
  101. error_log('user n password are ok');
  102. //Check if the account is active (not locked)
  103. if ($uData['active']=='1') {
  104. // check if the expiration date has not been reached
  105. if ($uData['expiration_date'] > date('Y-m-d H:i:s') OR $uData['expiration_date']=='0000-00-00 00:00:00') {
  106. //If Multiple URL is enabled
  107. if (api_get_multiple_access_url()) {
  108. //Check the access_url configuration setting if the user is registered in the access_url_rel_user table
  109. //Getting the current access_url_id of the platform
  110. $current_access_url_id = api_get_current_access_url_id();
  111. // my user is subscribed in these
  112. //sites: $my_url_list
  113. $my_url_list = api_get_access_url_from_user($uData['user_id']);
  114. } else {
  115. $current_access_url_id = 1;
  116. $my_url_list = array(1);
  117. }
  118. $my_user_is_admin = UserManager::is_admin($uData['user_id']);
  119. if ($my_user_is_admin === false) {
  120. if (is_array($my_url_list) && count($my_url_list)>0 ) {
  121. if (in_array($current_access_url_id, $my_url_list)) {
  122. // the user has permission to enter at this site
  123. $_user['user_id'] = $uData['user_id'];
  124. $_user = api_get_user_info($_user['user_id']);
  125. Session::write('_user',$_user);
  126. event_login();
  127. // Redirect to homepage
  128. $sso_target = isset($sso['target']) ? $sso['target'] : api_get_path(WEB_PATH) .'.index.php';
  129. header('Location: '. $sso_target);
  130. exit;
  131. } else {
  132. // user does not have permission for this site
  133. $loginFailed = true;
  134. Session::erase('_uid');
  135. header('Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=access_url_inactive');
  136. exit;
  137. }
  138. } else {
  139. // there is no URL in the multiple
  140. // urls list for this user
  141. $loginFailed = true;
  142. Session::erase('_uid');
  143. header('Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=access_url_inactive');
  144. exit;
  145. }
  146. } else {
  147. //Only admins of the "main" (first) Chamilo
  148. // portal can login wherever they want
  149. if (in_array(1, $my_url_list)) {
  150. //Check if this admin is admin on the
  151. // principal portal
  152. $_user['user_id'] = $uData['user_id'];
  153. $_user = api_get_user_info($_user['user_id']);
  154. $is_platformAdmin = $uData['status'] == COURSEMANAGER;
  155. Session::write('is_platformAdmin', $is_platformAdmin);
  156. Session::write('_user',$_user);
  157. event_login();
  158. self::redirect_to($sso, $_user['user_id'], true);
  159. } else {
  160. //Secondary URL admin wants to login
  161. // so we check as a normal user
  162. if (in_array($current_access_url_id, $my_url_list)) {
  163. $_user['user_id'] = $uData['user_id'];
  164. $_user = api_get_user_info($_user['user_id']);
  165. Session::write('_user',$_user);
  166. event_login();
  167. self::redirect_to($sso, $_user['user_id'], true);
  168. } else {
  169. $loginFailed = true;
  170. Session::erase('_uid');
  171. header('Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=access_url_inactive');
  172. exit;
  173. }
  174. }
  175. }
  176. } else {
  177. // user account expired
  178. $loginFailed = true;
  179. Session::erase('_uid');
  180. header('Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=account_expired');
  181. exit;
  182. }
  183. } else {
  184. //User not active
  185. $loginFailed = true;
  186. Session::erase('_uid');
  187. header('Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=account_inactive');
  188. exit;
  189. }
  190. } else {
  191. //SHA1 of password is wrong
  192. $loginFailed = true;
  193. Session::erase('_uid');
  194. header('Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=wrong_password');
  195. exit;
  196. }
  197. } else {
  198. //Auth_source is wrong
  199. $loginFailed = true;
  200. Session::erase('_uid');
  201. header('Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=wrong_authentication_source');
  202. exit;
  203. }
  204. } else {
  205. //No user by that login
  206. $loginFailed = true;
  207. Session::erase('_uid');
  208. header('Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=user_not_found');
  209. exit;
  210. }
  211. return $loginFailed;
  212. }
  213. /**
  214. * Decode the cookie (this function may vary depending on the
  215. * Single Sign On implementation
  216. * @param string Encoded cookie
  217. * @return array Parsed and unencoded cookie
  218. */
  219. private function decode_cookie($cookie) {
  220. return unserialize(base64_decode($cookie));
  221. }
  222. }