I want to try it with zend authentication component. I'd like to use bcrypt algorithm with dbTable authentication adapter.
Unfortunately, ZF2 has no built-in auth adapter for this.
Ok, let's make our own auth adapter based on DbTable auth adapter.
The logic is:
- fetch all rows from table where identity column value is equal to value of identity field from login form(it could be login name, email, etc)
- check if entered password is valid using bcrypt->verify() method
Implementation:
1. Create class that extends DbTable auth adapter
// define namespace for the class
namespace SomeModule\Auth\Adapter;
class BcryptDbAdapter extends DbTable
{
}
2. It is necessary to redefine two methods in our new class.
First method: authenticateCreateSelect() - method that creates a Zend\Db\Sql\Select object for fetching data from database
Second method: authenticateQuerySelect() - method that fetches data from database using Zend\Db\Sql\Select object from previous method.
Our class will look like below:
namespace SomeModule\Auth\Adapter;
use Zend\Authentication\Adapter\DbTable;
use Zend\Db\Sql;
use Zend\Db\Sql\Predicate\Operator as SqlOp;
class BcryptDbAdapter extends DbTable
{
    protected function authenticateCreateSelect()
    {
        // get select
        $dbSelect = clone $this->getDbSelect();
        $dbSelect->from($this->tableName)
            ->columns(array('*'))
            ->where(new SqlOp($this->identityColumn, '=', $this->identity));
        return $dbSelect;
    }
    protected function authenticateQuerySelect(Sql\Select $dbSelect)
    {
        $sql = new Sql\Sql($this->zendDb);
        $statement = $sql->prepareStatementForSqlObject($dbSelect);
        try {
            $result = $statement->execute();
            $resultIdentities = array();
            // create object ob Bcrypt class
            $bcrypt = new \Zend\Crypt\Password\Bcrypt();
            // iterate result, most cross platform way
            foreach ($result as $row) {
                if ($bcrypt->verify($this->credential, $row[$this->credentialColumn])) {
                    $row['zend_auth_credential_match'] = 1;
                    $resultIdentities[] = $row;
                }
            }
        } catch (\Exception $e) {
            throw new Exception\RuntimeException(
                'The supplied parameters to DbTable failed to '
                    . 'produce a valid sql statement, please check table and column names '
                    . 'for validity.', 0, $e
            );
        }
        return $resultIdentities;
    }
}
3. How to use example.- Add required namespaces to controller:
use SomeModule\Auth\Adapter\BcryptDbAdapter as AuthAdapter; use Zend\Authentication\AuthenticationService;
- Authenticate user in login action:
$data = $request->getPost();
$dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$authAdapter = new AuthAdapter($dbAdapter);
$authAdapter
  ->setTableName('users')
  ->setIdentityColumn('email')
  ->setCredentialColumn('password');
$authAdapter
  ->setIdentity(addslashes($data['email']))
  ->setCredential($data['password']);
// attempt authentication
$result = $authAdapter->authenticate();
if (!$result->isValid()) {
  // Authentication failed
} else {
  $auth = new AuthenticationService();
  $storage = $auth->getStorage();
  $storage->write($authAdapter->getResultRowObject(
    null,
    'password'
  ));
}
Source code is available on GitHub