dolibarr 24.0.0-beta
api_login.class.php
1<?php
2/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
3 * Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
5 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21use Luracast\Restler\RestException;
22
23require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
24require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
25
29class Login
30{
34 public $db;
35
39 public function __construct()
40 {
41 global $db;
42 $this->db = $db;
43
44 if (!getDolGlobalInt('API_ENABLE_LOGIN_API')) {
45 throw new RestException(403, "Error: The login APIs are disabled. It is recommended to call the APIs using the DOLAPIKEY token of an allowed user instead of the login/password. API key can be set from the user card. If you really need to get the API token from the login API, you can set the constant API_ENABLE_LOGIN_API.");
46 }
47 }
48
70 public function loginUnsecured($login, $password, $entity = '', $reset = 0)
71 {
72 return $this->index($login, $password, $entity, $reset);
73 }
74
96 public function index($login, $password, $entity = '', $reset = 0)
97 {
98 global $dolibarr_main_authentication, $dolibarr_auto_user;
99
100 // Is the login API disabled ? The token must be generated from backoffice only.
101 if (!getDolGlobalString('API_ENABLE_LOGIN_API')) {
102 dol_syslog("Warning: A try to use the login API has been done while the login API is disabled (Option API_ENABLE_LOGIN_API is off). You must generate or get the DOLAPIKEY token from the backoffice instead of using the /login API.", LOG_WARNING);
103 throw new RestException(403, "Error, the login API has been disabled for security purpose (Option API_ENABLE_LOGIN_API is off). You must generate or get the DOLAPIKEY token from the backoffice instead of using the /login API.");
104 }
105
106 // Authentication mode
107 if (empty($dolibarr_main_authentication) || $dolibarr_main_authentication == 'openid_connect') {
108 $dolibarr_main_authentication = 'dolibarr';
109 }
110
111 // Authentication mode: forceuser
112 if ($dolibarr_main_authentication == 'forceuser') {
113 if (empty($dolibarr_auto_user)) {
114 $dolibarr_auto_user = 'auto';
115 }
116 if ($dolibarr_auto_user != $login) {
117 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.");
118 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.");
119 }
120 }
121
122 // Set authmode
123 $authmode = explode(',', $dolibarr_main_authentication);
124
125 if ($entity != '' && !is_numeric($entity)) {
126 throw new RestException(403, "Bad value for entity, must be the numeric ID of company.");
127 }
128 if ($entity == '') {
129 $entity = 1;
130 }
131
132 include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
133 $login = checkLoginPassEntity($login, $password, $entity, $authmode, 'api'); // Check credentials.
134 if ($login === '--bad-login-validity--') {
135 $login = '';
136 }
137 if (empty($login)) {
138 throw new RestException(403, 'Access denied');
139 }
140
141 $token = 'failedtogenerateorgettoken';
142
143 $tmpuser = new User($this->db);
144 $tmpuser->fetch(0, $login, '0', 0, $entity);
145 if (empty($tmpuser->id)) {
146 throw new RestException(500, 'Failed to load user');
147 }
148
149 // Renew the hash
150 if (empty($tmpuser->api_key) || $reset) {
151 $tmpuser->loadRights();
152 if (!$tmpuser->hasRight('user', 'self', 'creer')) {
153 if (empty($tmpuser->api_key)) {
154 throw new RestException(403, 'No API token set for this user and user need write permission on itself to reset its API token');
155 } else {
156 throw new RestException(403, 'User need write permission on itself to reset its API token');
157 }
158 }
159
160 // Generate token for user
161 $token = dol_hash($login.bin2hex(random_bytes(32)).getDolGlobalString('MAIN_API_KEY'), 'hash');
162
163 // We store API token into database
164 $sql = "UPDATE ".MAIN_DB_PREFIX."user";
165 $sql .= " SET api_key = '".$this->db->escape(dolEncrypt($token, '', '', 'dolibarr'))."'";
166 $sql .= " WHERE login = '".$this->db->escape($login)."'";
167
168 dol_syslog(get_class($this)."::login", LOG_DEBUG); // No log
169 $result = $this->db->query($sql);
170 if (!$result) {
171 throw new RestException(500, 'Error when updating api_key for user :'.$this->db->lasterror());
172 }
173 } else {
174 $token = $tmpuser->api_key;
175 if (!utf8_check($token)) {
176 throw new RestException(500, 'Error, the API token of this user has a non valid value. Try to update it with a valid value.');
177 }
178 }
179
180 if (!ascii_check($token)) {
181 throw new RestException(500, 'Error the token for this user has not an hexa format. Try first to reset it.');
182 }
183
184 //return token
185 return array(
186 'success' => array(
187 'code' => 200,
188 'token' => $token,
189 'entity' => $tmpuser->entity ?? 1,
190 '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.')
191 )
192 );
193 }
194}
API that allows to log in with an user account.
__construct()
Constructor of the class.
index($login, $password, $entity='', $reset=0)
Login.
loginUnsecured($login, $password, $entity='', $reset=0)
Login.
Class to manage Dolibarr users.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
ascii_check($str)
Check if a string is in ASCII.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
utf8_check($str)
Check if a string is in UTF8.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
checkLoginPassEntity($usertotest, $passwordtotest, $entitytotest, $authmode, $context='')
Return a login if login/pass was successful.
dol_hash($chain, $type='0', $nosalt=0, $mode=0)
Returns a hash (non reversible encryption) of a string.
dolEncrypt($chain, $key='', $ciphering='', $forceseed='', $obfuscationmode='dolcrypt')
Encode a string with a symmetric encryption.