My problem is that I'm using CodeIgniter. I created an Administrator Panel which I use to create users and passwords. I use password_hash before sending them to database (in fact, in the database I can see the hashed password).
The problem is... When I try to log in, it doesn't. I can only access with administrator account, which I created before I started using CodeIgniter.
I can log in with admin account, but not with the accounts created with the admin panel.
I tried to use a very simple php file (outside CI) to copy and paste the hash to one of the user's fields in my database and it worked. I don't understand why this doesn't work within CodeIgniter.
Here's the part of my code:
public function insert_user($username, $passw, $perm){
$hashed_pass = password_hash($passw, PASSWORD_DEFAULT);
$data = array(
"username" => $username,
"passw" => $hashed_pass,
"perms" => $perm
);
$this->db->insert('usuarios', $datos);
}
The function above inserts correctly data in the database. I can see the password hashed, but when I try to log in with created users from admin panel, it just doesn't work (but it does with admin account, and they all are using the same function to log in).
public function login($username, $password){
$query = $this->db->query("select passw, perms from users where username = '".$username."'");
$result = $query->row();
$p_hashed = $result->passw;
$perms= $result->perms;
if(password_verify($password, $p_hashed)){
$info= array(
"is_valid" => true,
"username" => $username,
"perms" => $perms
);
return $info;
}
else {
$info= array(
"is_valid" => false,
"username" => ""
);
return $info;
}
}
I checked database and CI charset, all is utf8. I don't understand why is not working... I would appreciate any help.
P.S.: if the name of variables are no correlated or are not the same is because I translated it to English (I'm not native English speaker, so I'm not using English in this project).
Thank you.
EDIT
I've changed the code to use md5 instead of password_hash and I'm having the same issue.
EDIT 2
I detected the problem: I was comparing the 2 password (the first one and the confirm password). After that comparison, I passed the data to the model... But the variable of the password I was sending to model was a new variable with no data. I was hashing a not initialized variable.
There doesn't seem to be any problem in the code you show. As I commented, the likely problem is that the passw column in the table is truncating the data being inserted.
Check the documentation for password_hash to find what the return data size is for the various algorithms and adjust your table structure accordingly. For PASSWORD_DEFAULT the suggested size is 255 characters.
The code below isn't an answer, but I have time and thought you might find a refactored version of login() interesting.
It is assumed that you have properly validated and sanitized the values being passed to the login() method.
public function login($username, $password)
{
//use query binding so values are automatically escaped, producing a safer query
$query = $this->db->query("select username, perms, passw
from users where username = ?", [$username]);
// make sure query worked and found a record
if($query && $query->num_rows() > 0)
{
// get an row array so you don't need to make an array
$row = $query->row_array();
if(password_verify($password, $row['passw']))
{
unset($row['passw']); // remove passw from array
$row['is_valid'] = true;
return $row;
}
}
return array( "is_valid" => false, "username" => "");
}
Related
I'm trying to manually login a frontend user (and do some other basic operations while I'm at it) in an ajaxAction and it doesn't seem to work as I intend. What I do when the loginform is submitted:
$loginData = array(
'username' => $username,
'uident_text' => $password,
'status' => 'login',
);
$GLOBALS['TSFE']->fe_user->checkPid = 0;
$info = $GLOBALS['TSFE']->fe_user->getAuthInfoArray();
$user = $GLOBALS['TSFE']->fe_user->fetchUserRecord($info['db_user'], $loginData['username']);
$GLOBALS['TSFE']->loginUser = 1;
$GLOBALS['TSFE']->fe_user->createUserSession($user);
$GLOBALS['TSFE']->fe_user->setAndSaveSessionData('user', TRUE);
return json_encode(['login' => 'true']);
when trying to print out $GLOBALS['TSFE']->fe_user before the return, the data are set and $GLOBALS['TSFE']->loginUser = 1 , so everything looks file. When I reload the login form afterwards though, the fe_user data are still there, but the fluid security.ifAuthenticated does not work.
The Form view looks like this:
<f:security.ifAuthenticated>
<f:then>
user is authenticated!
</f:then>
<f:else>
<f:render partial="LoginForm.html"/>
</f:else>
</f:security.ifAuthenticated>
Username: {user.firstName}
And it corretly outputs the Firstname of the logged in user, but also still shows the loginform. security.ifAuthenticated always enters the ELSE. And when I looked at the viewHelper it is because $GLOBALS['TSFE']->loginUser is not set.
Any hints/ideas as to why this is happening?
From what I experimented, you need to set a cookie for it to work.
$reflection = new \ReflectionClass($GLOBALS['TSFE']->fe_user);
$setSessionCookieMethod = $reflection->getMethod('setSessionCookie');
$setSessionCookieMethod->setAccessible(TRUE);
$setSessionCookieMethod->invoke($GLOBALS['TSFE']->fe_user);
If I played only with $GLOBALS['TSFE']->fe_users, it didn't work even if the fe_session was created in the database.
Turns out my inexperience with typo3 and the fe_login was at fault. What I did not know is that $GLOBALS['TSFE']->loginUser is an indicator of fe_groups. The problem was, that my frontend user was not assigned to a group, the column "usergroup" was empty in the database. Therefore Typo3 sets loginUser back to false and that's why ifAuthenticated does not work.
I wrote about the solution here, but basically the only thing I did was assign the user to a group and afterwards the login as I tried it worked fine.
I'm trying to make my first Moodle auth extension where I want to confirm and login users directly after signup.
I've changed the user_signup function in the "email" auth plugin like this:
\core\event\user_created::create_from_userid($user->id)->trigger();
$DB->set_field("user", "confirmed", 1, array("id"=>$user->id));
$user = get_complete_user_data('username', $username);
$DB->set_field("user", "firstaccess", time(), array("id"=>$user->id));
$DB->set_field("user", "lastlogin", 0, array("id"=>$user->id));
update_user_login_times($user);
complete_user_login($user);
redirect("$CFG->wwwroot/enrol/index.php?id=2");
It works so far as the user gets signed up and confirmed. But as for the login I get the following error:
core\session\manager::login_user() must be an instance of stdClass, boolean given
I might be acting stupid here, but I don't know how I could login the new user here. Any help would be very much apprechiated. Thanks!
After Creating user account get username and password that you have entered and then implement like this.
if ($user = authenticate_user_login($username, $password)) {
/// Let's get them all set up.
complete_user_login($user);
redirect($CFG->wwwroot . 'URL you want');
}
i am trying to login to my admin panel by using $this->Auth->login(), but it always returns false, i have tried as much as i can, now i need your help to sort out this problem, here is my code from controller file:
class BrownieController extends BrownieAppController {
public $uses = array('User');
public function login() {
echo "<pre>";
print_r($this->request->data);
echo "</pre>";
if ($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
} else {
if($this->request->isPost()) {
$this->Auth->flash(__('Invalid username or password, try again'));
}
}
}
On print_r the data, it shows:
Array
(
[User] => Array
(
[email] => admin#xin.com
[password] => admin#123
)
)
which is the exact info stored in users table in my database.
Any help will be appreciated.
Should have been 'username' instead of 'email' in the request data unless you have changed the configurations
Reason 1:
$this->Auth->login takes data in the form of
array(
'User'=>array(
'username'=>'myusername',
'password'=>'mypassword'
)
)
Reason 2:
You must send the password exactly as it appears in the database.
EVERYTHING BELOW THIS LINE IS POSSIBLE BUT NOT LIKELY IN THIS CASE:
Are you sure that when you originally created the username and password, the hashes were setup?
To check that your hashes match look at your users table with phpmyadmin or mysql workbench and find the password field for the user chris22
Compare that entry to your current hashing. To check your current hash, put the code below somewhere in a controller function (index) and navigate there.
debug(Security::hash('stuff'));
exit;
Also you can see the cakephp for login and logout docs.
I hope this helps!
I need to do some extra checks on a user, I would like to get the user by username and password.
Firstly:
Is there a built in function that gets a user by username and password without authenticating them?
Secondly:
If the above is no, then how do I correctly hash the password, because if I use Hash::make( $password ) and then compare to the database, it is not the same... You would usually use Hash::check but I need to actually get the user by username and password.
In Laravel 5.2
You can use Auth::once($credentials) to validate credentials and thereafter Auth::getUser(); to get the user.
$credentials = Request::only('username', 'password');
if(!Auth::once($credentials)) {
// Invalid user credentials; throw Exception.
}
$user = Auth::getUser();
First:
If you want to check if user data to authentication is correct you can use:
if (Auth::validate($credentials))
{
//
}
But if you want to get user from database with user and password, you can use:
$user = User::whereName($username)->wherePassword(Hash::make($password))->first();
Second
To store password in database you should use Hash::make($password) as you showed and it works without any problems. Using Auth::validate should solve the issue.
Yes, there is a built in function you should use. I recommend you to read the docs. But here's a good example, it's pretty self-evident:
$input = array(
'username' => Input::get('username'),
'password' => Input::get('password'),
);
$remember = (boolean)Input::get('remember'); //'Remember me' checkbox
if (Auth::attempt($input, $remember)) {
return Redirect::intended('dashboard')->with("success", "You're logged in!"); //Redirect the user to the page intended to go to, with the dashboard page as default
}
Registering a user looks something like this:
$input = array(
'username' => Input::get('username'),
'email' => Input::get('email'),
'password' => Hash::make(Input::get('password')) //Encrypt password
);
$user = User::create($input);
I also recommend you to read about input validation. I hope this helps, good luck.
Edit: I didn't read the "without authenticating them" part. You should use Auth::validate($input) as Marcin already explained.
Laravel 5.7
To check a users credentials without logging them in, I had to do this:
$user = User::whereEmail($request->email)->first();
$user = password_verify($request->password, optional($user)->getAuthPassword()) ? $user : false;
Laravel auth validation makes use of https://www.php.net/manual/en/function.password-verify.php
I have the following code:
MODEL:
function check_account($account_details){
$query = $this->db->get_where('admin', array('username' => $account_details['username'] ,
'password' => $account_details['password']) )->result_array();
if(!empty($query)){
return 'Admin';
}
else{
$query2 = $this->db->get_where('user_mst', array('username' => $account_details['username'],
'password' => $account_details['password']) )->result_array();
if(!empty($query2)){
return 'User';
}
else return FALSE;
}
}
I only posted my model because view only consist of input fields for username and password and in the controller it only retrieves the data inputted and passed on to the function in the model. The above code snippet is the function which was called by the controller.
I only have 1 log in page, it checks first if the account inputted exists in the admin table, if not, then checks if it exists in the user table. IF the account inputted does not belong to the 2 tables, it returns false.
I checked admin table first because accounts in the admin belongs to the minority. whereas in the user will be most of the majority accounts. For example, if i have 5 admin accounts and 1000 user accounts.
Instead of checking if the account inputted is one of those 1000 it firsts checks if it belongs to the 5 in the admin table.
Hope my explanation is clear or at least understandable.
My question is, when i input say, SampleAccount as username even though in the database its all in small caps it still returns as though its the same.
SampleAccount(inputted) = sampleaccount(database) - should not return in the query.
Also, i would like to read some professional's opinion on how im checking the account, or should i just make 2 login pages for both user and admins.
foreach($query as $arr => $result){
if($account_details['username'] == $result['username']){
echo ' equal';
}
else echo ' not equal';
}
If inputted is UseRname and in the database it is Username then this is ideal.
But is there anyway, to add this in the query itself?
get_where(); like limit, etc.
bro you had big mistake make 1 table but make coulmn name it role
check if 1 user 2 admin
function premission_check($role){
switch($role){
case 1 :
return 'user';
break;
case 2 :
return 'admin';
break;
default :
return 'bad role'
break;
}}