Reputation: 88
Until now I have stored all passwords in plain text because the site is not live and I decided to wait for the new password api.
I have this code working for passwords in plain text:
<?php
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('account')
->setIdentityColumn('account_id')
->setCredentialColumn('account_password');
// Get our authentication adapter and check credentials
$adapter = $authAdapter;
$adapter->setIdentity($values['account_id']);
$adapter->setCredential($values['password']);
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($adapter);
if ($result->isValid()) {
$user = $adapter->getResultRowObject();
$auth->getStorage()->write($user);
return true;
}
return false;
According to docs I should implement my own adapter and probably just change to make use of password_verify().
I'm missing the big picture here to how everything is working together.
My question is:
$authAdaper
or $auth
Any high level (or low level :D) example code would be appreciated.
All best Adam
Upvotes: 2
Views: 1207
Reputation: 2260
Hashes created by password_hash()
needs to be compared via ̀password_verify()` because 2 hashes for the same password are not always equals (at least not with BCRYPT or ARGON2).
<?php
$pass = 'foo';
var_dump(password_hash($pass, PASSWORD_BCRYPT) === password_hash($pass, PASSWORD_BCRYPT));
// bool(false)
var_dump(password_verify($pass, password_hash($pass, PASSWORD_BCRYPT)));
// bool(true)
Someone (s7anley) did a Zend_Auth_Adapter_DbTable
extension that uses password_verify(), here it is (for reference):
<?php
class Base_Auth_Adapter_BcryptDbTable extends Zend_Auth_Adapter_DbTable
{
/**
* @inheritdoc
*/
protected function _authenticateCreateSelect()
{
$dbSelect = clone $this->getDbSelect();
$dbSelect->from($this->_tableName)
->where($this->_zendDb->quoteIdentifier($this->_identityColumn, true) . ' = ?', $this->_identity);
return $dbSelect;
}
/**
* @inheritdoc
*/
protected function _authenticateValidateResult($resultIdentity)
{
$passwordCheck = password_verify($this->_credential, $resultIdentity[$this->_credentialColumn]);
if (!$passwordCheck) {
$this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
$this->_authenticateResultInfo['messages'][] = 'Supplied credential is invalid.';
return $this->_authenticateCreateAuthResult();
}
$this->_resultRow = $resultIdentity;
$this->_authenticateResultInfo['code'] = Zend_Auth_Result::SUCCESS;
$this->_authenticateResultInfo['messages'][] = 'Authentication successful.';
return $this->_authenticateCreateAuthResult();
}
}
The class name says "Bcrypt" but it will work just fine with any algorithm supported by password_hash()
.
You can use it like that:
$authAdapter = new Base_Auth_Adapter_BcryptDbTable($databaseAdapter, 'users', 'login', 'password');
$authAdapter
->setIdentity('my_username')
->setCredential('my_password') // "clear" password
// ->setCredentialTreatment(null) // Can't set any treatment on password (would be ignored)
;
// For any additional filtering of returned rows, use getDbSelect()
$authAdapter->getDbSelect()->where('active = "TRUE"');
Upvotes: 1
Reputation: 9857
If you are looking to modify the way in which your authentication operates by adding the password_hash
encryption then
you will need to do so within PHP
.
As you still wish to use database authentication I think recreating this as a new adapter would be overkill. You could however, extend the current database adapter, such as:
class My_Auth_Adapter_DbTable extends Zend_Auth_Adapter_DbTable
{
public function setCredential($credential)
{
$this->_credential = password_hash($credential);
return $this;
}
}
This means that any password provided to the adapter will always be encrypted with the password_hash
function.
This could however be acomplished outside the adapter by hashing the password prior to the call to setCredential
.
$options = array('salt' => $config->passwordSalt);
$hashPassword = password_hash($plainTextPassword, PASSWORD_BCRYPT, $options);
$adpater->setCredential($hashPassword);
This method will allow you to modify the optional parameters before passing to the adapter.
Lastly, it is worth mentioning that the setCredentialTreatment
method is normally used to provided password encryption, which is performed within the SQL statement (meaning you will need to use the MySQL commands and not password_hash
).
$authAdapter->setTableName('user')
->setIdentityColumn('email')
->setCredentialColumn('password')
->setCredentialTreatment(sprintf("MD5(CONCAT(?,'%s'))", $config->passwordSalt));
Upvotes: 1