Sephen
August 27, 2022, 8:02am
1
How can I authenticate a user with a username and password via the API?
In the previous version you could (in config/public/api/auth/php) do
return $this->invoke('Cockpit\\Controller\\RestApi', 'authUser');
But apparently this doesn’t work anymore.
Thanks in advance!
2 Likes
poe
October 27, 2022, 8:25am
2
I’m also looking for this feature in V2.
I know this isn’t easy to implement in V2.
I wish @artur answer us how to implement it or the right way to get API key with username and password. Thanks
Found a way for that.
Generate the api key of the user from the admin panel.
Edit app.user.disguise
event in /modules/App/bootstrap.php
and comment or delete the $user['apiKey']
item.
$this->on('app.user.disguise', function(array &$user) {
unset($user['password'], /* $user['apiKey'], */ $user['_reset_token']);
});
Edit /modules/App/Controller/Auth.php
and add this new function:
public function apiLogin() {
$auth = $this->param('auth');
if (!$auth || !isset($auth['email'], $auth['password']) || !\is_string($auth['email']) || !\is_string($auth['password'])) {
return $this->stop(412);
}
$user = $this->helper('auth')->authenticate($auth, true);
if ($user) {
return ['success' => true, 'user' => $user];
}
return ['success' => false];
}
Edit modules\App\Helper\Auth.php
and modify the authenticate
function:
public function authenticate(array $data, $forApi = false): mixed {
$data = array_merge([
'user' => '',
'email' => '',
'password' => ''
], $data);
if (!$data['password']) return false;
$filter = ['active' => true];
if ($data['email']) {
$filter['email'] = $data['email'];
} else {
$filter['user'] = $data['user'];
}
$user = $this->app->dataStorage->findOne('system/users', $filter);
if ($user && (password_verify($data['password'], $user['password']))){
$user = array_merge($data, (array)$user);
unset($user['password']);
if (!$forApi) {
$this->app->trigger('app.user.authenticate', [&$user]);
}
return $user;
}
return false;
}
Now you can get the whole user info and its api key from /api/auth/apiLogin
endpoint with the request body below:
{ auth: { email: "xyz@example.com", password: "Abc123@" } }
I don’t sure exposing the disguised api key is a good idea, but it works.
1 Like
Thanks @ronaldaug , yes this is a safer approach. But I think it would be better to return users’ own api key instead of sending a fixed one for everyone. It will cause that every cruds are made by the same user.
artur
November 10, 2022, 12:37pm
6
In Cockpit you can create (file based) custom api end points pretty easy within the config folder.
Create a file (with folder path) in the root folder:
config/api/user/auth.php
with the following contents:
<?php
$user = $this->param('user');
$password = $this->param('password');
if (!$user || !$password) {
return $this->stop(['error' => 'User and password are required'], 412);
}
$user = $this->helper('auth')->authenticate(compact('user', 'password'));
if (!$user) {
return $this->stop(['error' => 'Authentication failed!'], 412);
}
return ['apiKey' => $user['apiKey']];
Now you can run requests against /api/user/auth
2 Likes
@artur This solution worked perfectly for my frontend, Thanks.
one question, previously we had /api/cockpit/saveUser & /api/cockpit/listUsers for saving and listing user from cockpit v1. how do we accomplish the same in latest cockit 2.3 v2? help will be highly appreciated, stuck over this problem form sometime now,without success
1 Like
This is my current status:
<?php
$user = "tesqtme";
$name= "tesqtme";
$email= "testqme@gmail.com";
$password = "123456";
$role= "admin";
$created = time();
$app = Cockpit::instance();
$userExist = $this->app->dataStorage->findOne('system/users', ['user' => $user]);
$emailExist = $this->app->dataStorage->findOne('system/users', ['email' => $email]);
// echo $userExist;
// echo $emailExist;
// echo "done";
$user = [
'active' => true,
'user' => $user,
'name' => $name,
'email' => $email,
'password' => $app->hash('$password'),
'i18n' => 'en',
'role' => 'admin',
'theme' => 'auto',
'_modified' => $created,
'_created' => $created
];
$app->dataStorage->save('system/users', $user);
// return [ $userExist => $emailExist];
//if (!$userExist && !$emailExist ){
?>
Plz let me know how to proceed “properly” from this point.
Still trying to figure a way to list all users though, plus only admin or “editor” should be able to do that, currently i am able to count (though that path is public)
<?php
$app = Cockpit::instance();
if ($app->dataStorage->getCollection('system/users')->count()) {
$users= $app->dataStorage->getCollection('system/users')->count();
echo $users ;
exit;
}
?>
2 Likes
Hello. If i want to have a list of the users and not de number of users. What I need to change in this code ?
Thank’s
Pcharli
December 18, 2023, 11:08am
11
Hello Artur.
Thank’s for your help.
But, in the config/api/user/list.php i have this code
<?php
$app = Cockpit::instance();
if ($app->dataStorage->getCollection('system/users')->count()) {
$users= $app->dataStorage->getCollection('system/users')->count();
$usersv= $app->dataStorage->getCollection('system/users')->findOne();
$usersv["nb"] = $users;
echo json_encode($usersv);
//echo $users ;
exit;
}
I want to see the users list but de find function don’t worls and the findOne function return me the first user.
Have You one idea ?
Thank’s
1 Like