Db.php 3.7 KB
Newer Older
Bertrand Gauthier's avatar
Bertrand Gauthier committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<?php
namespace UnicaenAuth\Authentication\Adapter;

use Zend\Authentication\Result as AuthenticationResult;
use Zend\Crypt\Password\Bcrypt;
use ZfcUser\Authentication\Adapter\AdapterChainEvent;
use ZfcUser\Authentication\Adapter\AdapterChainEvent as AuthEvent;
use \UnicaenAuth\Options\AuthenticationOptionsInterface;

/**
 * Db authentication adpater with sesame password check.
 *
 * @author Bertrand GAUTHIER <bertrand.gauthier@unicaen.fr>
 */
class Db extends \ZfcUser\Authentication\Adapter\Db
{
    /**
     * @var AuthenticationOptionsInterface
     */
    protected $unicaenUserOptions;

    /**
     * 
     * @param AdapterChainEvent $e
     * @return boolean
     */
    public function authenticate(AuthEvent $e)
    {
        if ($this->isSatisfied()) {
            $storage = $this->getStorage()->read();
            $e->setIdentity($storage['identity'])
              ->setCode(AuthenticationResult::SUCCESS)
              ->setMessages(array('Authentication successful.'));
            return;
        }

        $identity   = $e->getRequest()->getPost()->get('identity');
        $credential = $e->getRequest()->getPost()->get('credential');
        $credential = $this->preProcessCredential($credential);
        $userObject = NULL;

        // Cycle through the configured identity sources and test each
        $fields = $this->getOptions()->getAuthIdentityFields();
        while ( !is_object($userObject) && count($fields) > 0 ) {
            $mode = array_shift($fields);
            switch ($mode) {
                case 'username':
                    $userObject = $this->getMapper()->findByUsername($identity);
                    break;
                case 'email':
                    $userObject = $this->getMapper()->findByEmail($identity);
                    break;
            }
        }

        if (!$userObject) {
            $e->setCode(AuthenticationResult::FAILURE_IDENTITY_NOT_FOUND)
              ->setMessages(array('A record with the supplied identity could not be found.'));
            $this->setSatisfied(false);
            return false;
        }

        $bcrypt = new Bcrypt();
        $bcrypt->setCost($this->getOptions()->getPasswordCost());
        if (!$bcrypt->verify($credential,$userObject->getPassword())) {
            // Password does not match, try sesame
            if (!($sesame = $this->getUnicaenAuthOptions()->getSesamePassword()) || !$bcrypt->verify($credential, $sesame)) {
                $e->setCode(AuthenticationResult::FAILURE_CREDENTIAL_INVALID)
                  ->setMessages(array('Supplied credential is invalid.'));
                $this->setSatisfied(false);
                return false;
            }
        }

        // Success!
        $e->setIdentity($userObject->getId());
        // Update user's password hash if the cost parameter has changed
        $this->updateUserPasswordHash($userObject, $credential, $bcrypt);
        $this->setSatisfied(true);
        $storage = $this->getStorage()->read();
        $storage['identity'] = $e->getIdentity();
        $this->getStorage()->write($storage);
        $e->setCode(AuthenticationResult::SUCCESS)
          ->setMessages(array('Authentication successful.'));
    }

    /**
     * @param AuthenticationOptionsInterface $options
     */
    public function setUnicaenAuthOptions(AuthenticationOptionsInterface $options)
    {
        $this->unicaenUserOptions = $options;
    }

    /**
     * @return AuthenticationOptionsInterface
     */
    public function getUnicaenAuthOptions()
    {
        if (!$this->unicaenUserOptions instanceof AuthenticationOptionsInterface) {
101
            $this->setUnicaenAuthOptions($this->getServiceManager()->get('unicaen-auth_module_options'));
Bertrand Gauthier's avatar
Bertrand Gauthier committed
102
103
104
105
106
        }
        return $this->unicaenUserOptions;
    }

}