public function verifyCredentials($user, $password)
{
$this->debug('verifying credentials for ' . $user . ' ' . $password);
// First, perhaps model has a method for verifying credentials.
if ($this->model->hasMethod('verifyCredentials')) {
return $this->model->verifyCredentials($user, $password);
}
// If password field is not defined in the model for security
// reasons, let's add it for authentication purpose.
$password_existed = true;
if (!$this->model->hasElement($this->password_field)) {
$this->model->addField($this->password_field)->type('password');
$password_existed = false;
}
// Attempt to load user data by username. If not found, return false
/** @type Model $data User model */
$data = $this->model->newInstance();
$data->tryLoadBy($this->login_field, $user);
if (!$data->loaded()) {
$this->debug('user with login ' . $user . ' could not be loaded');
if (!$password_existed) {
$data->getElement($this->password_field)->destroy();
}
return false;
}
$hash = $data[$this->password_field];
$this->debug('loaded user entry with hash: ' . $hash);
// Verify password first
$result = false;
$rehash = false;
if ($this->password_encryption == 'php') {
// Get information about the hash
$info = password_get_info($hash);
// Backwards-compatibility with older ATK encryption methods
if ($info['algo'] == 0) {
// Determine type of hash by length
if (strlen($hash) == 64) {
$this->password_encryption = 'sha256/salt';
} elseif (strlen($hash) == 32) {
$this->password_encryption = 'md5';
} elseif (strlen($hash) == 40) {
$this->password_encryption = 'sha1';
} else {
$this->password_encryption = null;
$this->debug('Unable to identify password hash type, using plain-text matching');
/*
$this->password_encryption='php';
$data->unload();
if (!$password_existed) {
$data->getElement($this->password_field)->destroy();
}
return false;
*/
}
// Convert password hash
$this->debug('Old password found with algo=' . $this->password_encryption);
$ep = $this->encryptPassword($password, $user);
$this->password_encryption = 'php';
$rehash = true;
$result = $hash == $ep;
} else {
$result = password_verify($password, $ep = $data[$this->password_field]);
$this->debug('Native password hash with info: ' . json_encode($info));
$rehash = password_needs_rehash($hash, $this->hash_algo, $this->hash_options);
}
if ($result) {
$this->debug('Verify is a SUCCESS');
if ($rehash) {
$hash = $data[$this->password_field] = $password;
$data->setDirty($this->password_field);
$data->save();
$this->debug('Rehashed into ' . $data[$this->password_field]);
}
}
} else {
$ep = $this->encryptPassword($password, $user);
$result = $hash == $ep;
$this->debug('Attempting algo=' . $this->password_encryption . ' hash=' . $hash . ' newhash=' . $ep);
}
if (!$result) {
$this->debug('Verify is a FAIL');
$data->unload();
if (!$password_existed) {
$data->getElement($this->password_field)->destroy();
}
return false;
}
// Leave record loaded, but hide password
$data[$this->password_field] = '';
$data->dirty[$this->password_field] = false;
return $data[$this->model->id_field];
/*
if (!$password_existed) {
$data->getElement($this->password_field)->destroy();
}
*/
}