api_login.class.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <?php
  2. /* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
  3. * Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use Luracast\Restler\RestException;
  19. require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
  20. require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
  21. /**
  22. * API that allows to log in with an user account.
  23. */
  24. class Login
  25. {
  26. /**
  27. * @var DoliDB Database handler
  28. */
  29. public $db;
  30. /**
  31. * Constructor of the class
  32. */
  33. public function __construct()
  34. {
  35. global $conf, $db;
  36. $this->db = $db;
  37. //$conf->global->MAIN_MODULE_API_LOGIN_DISABLED = 1;
  38. if (getDolGlobalString('MAIN_MODULE_API_LOGIN_DISABLED')) {
  39. throw new RestException(403, "Error login APIs are disabled. You must get the token from backoffice to be able to use APIs");
  40. }
  41. }
  42. /**
  43. * Login
  44. *
  45. * Request the API token for a couple username / password.
  46. * WARNING: You should NEVER use this API, like you should never use the similare API that uses the POST method. This will expose your password.
  47. * To use the APIs, you should instead set an API token to the user you want to allow to use API (This API token called DOLAPIKEY can be found/set on the user page) and use this token as credential for any API call.
  48. * From the API explorer, you can enter directly the "DOLAPIKEY" into the field at the top right of the page to get access to any allowed APIs.
  49. *
  50. * @param string $login User login
  51. * @param string $password User password
  52. * @param string $entity Entity (when multicompany module is used). '' means 1=first company.
  53. * @param int $reset Reset token (0=get current token, 1=ask a new token and canceled old token. This means access using current existing API token of user will fails: new token will be required for new access)
  54. * @return array Response status and user token
  55. *
  56. * @throws RestException 403 Access denied
  57. * @throws RestException 500 System error
  58. *
  59. * @url GET /
  60. */
  61. public function loginUnsecured($login, $password, $entity = '', $reset = 0)
  62. {
  63. return $this->index($login, $password, $entity, $reset);
  64. }
  65. /**
  66. * Login
  67. *
  68. * Request the API token for a couple username / password.
  69. * WARNING: You should NEVER use this API, like you should never use the similare API that uses the POST method. This will expose your password.
  70. * To use the APIs, you should instead set an API token to the user you want to allow to use API (This API token called DOLAPIKEY can be found/set on the user page) and use this token as credential for any API call.
  71. * From the API explorer, you can enter directly the "DOLAPIKEY" into the field at the top right of the page to get access to any allowed APIs.
  72. *
  73. * @param string $login User login
  74. * @param string $password User password
  75. * @param string $entity Entity (when multicompany module is used). '' means 1=first company.
  76. * @param int $reset Reset token (0=get current token, 1=ask a new token and canceled old token. This means access using current existing API token of user will fails: new token will be required for new access)
  77. * @return array Response status and user token
  78. *
  79. * @throws RestException 403 Access denied
  80. * @throws RestException 500 System error
  81. *
  82. * @url POST /
  83. */
  84. public function index($login, $password, $entity = '', $reset = 0)
  85. {
  86. global $conf, $dolibarr_main_authentication, $dolibarr_auto_user;
  87. // Is the login API disabled ? The token must be generated from backoffice only.
  88. if (getDolGlobalString('API_DISABLE_LOGIN_API')) {
  89. dol_syslog("Warning: A try to use the login API has been done while the login API is disabled. You must generate or get the token from the backoffice.", LOG_WARNING);
  90. throw new RestException(403, "Error, the login API has been disabled for security purpose. You must generate or get the token from the backoffice.");
  91. }
  92. // Authentication mode
  93. if (empty($dolibarr_main_authentication)) {
  94. $dolibarr_main_authentication = 'dolibarr';
  95. }
  96. // Authentication mode: forceuser
  97. if ($dolibarr_main_authentication == 'forceuser') {
  98. if (empty($dolibarr_auto_user)) {
  99. $dolibarr_auto_user = 'auto';
  100. }
  101. if ($dolibarr_auto_user != $login) {
  102. dol_syslog("Warning: your instance is set to use the automatic forced login '".$dolibarr_auto_user."' that is not the requested login. API usage is forbidden in this mode.");
  103. throw new RestException(403, "Your instance is set to use the automatic login '".$dolibarr_auto_user."' that is not the requested login. API usage is forbidden in this mode.");
  104. }
  105. }
  106. // Set authmode
  107. $authmode = explode(',', $dolibarr_main_authentication);
  108. if ($entity != '' && !is_numeric($entity)) {
  109. throw new RestException(403, "Bad value for entity, must be the numeric ID of company.");
  110. }
  111. if ($entity == '') {
  112. $entity = 1;
  113. }
  114. include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
  115. $login = checkLoginPassEntity($login, $password, $entity, $authmode, 'api'); // Check credentials.
  116. if ($login === '--bad-login-validity--') {
  117. $login = '';
  118. }
  119. if (empty($login)) {
  120. throw new RestException(403, 'Access denied');
  121. }
  122. $token = 'failedtogenerateorgettoken';
  123. $tmpuser = new User($this->db);
  124. $tmpuser->fetch(0, $login, 0, 0, $entity);
  125. if (empty($tmpuser->id)) {
  126. throw new RestException(500, 'Failed to load user');
  127. }
  128. // Renew the hash
  129. if (empty($tmpuser->api_key) || $reset) {
  130. $tmpuser->getrights();
  131. if (!$tmpuser->hasRight('user', 'self', 'creer')) {
  132. if (empty($tmpuser->api_key)) {
  133. throw new RestException(403, 'No API token set for this user and user need write permission on itself to reset its API token');
  134. } else {
  135. throw new RestException(403, 'User need write permission on itself to reset its API token');
  136. }
  137. }
  138. // Generate token for user
  139. $token = dol_hash($login.uniqid().(!getDolGlobalString('MAIN_API_KEY') ? '' : $conf->global->MAIN_API_KEY), 1);
  140. // We store API token into database
  141. $sql = "UPDATE ".MAIN_DB_PREFIX."user";
  142. $sql .= " SET api_key = '".$this->db->escape(dolEncrypt($token, '', '', 'dolibarr'))."'";
  143. $sql .= " WHERE login = '".$this->db->escape($login)."'";
  144. dol_syslog(get_class($this)."::login", LOG_DEBUG); // No log
  145. $result = $this->db->query($sql);
  146. if (!$result) {
  147. throw new RestException(500, 'Error when updating api_key for user :'.$this->db->lasterror());
  148. }
  149. } else {
  150. $token = $tmpuser->api_key;
  151. if (!utf8_check($token)) {
  152. throw new RestException(500, 'Error, the API token of this user has a non valid value. Try to update it with a valid value.');
  153. }
  154. }
  155. if (!ascii_check($token)) {
  156. throw new RestException(500, 'Error the token for this user has not an hexa format. Try first to reset it.');
  157. }
  158. //return token
  159. return array(
  160. 'success' => array(
  161. 'code' => 200,
  162. 'token' => $token,
  163. 'entity' => $tmpuser->entity,
  164. 'message' => 'Welcome '.$login.($reset ? ' - Token is new' : ' - This is your token (recorded for your user). You can use it to make any REST API call, or enter it into the DOLAPIKEY field to use the Dolibarr API explorer.')
  165. )
  166. );
  167. }
  168. }