Db.php 4.46 KB
Newer Older
Bertrand Gauthier's avatar
Bertrand Gauthier committed
1
2
3
<?php
namespace UnicaenAuth\Authentication\Adapter;

4
5
use UnicaenApp\Exception;
use UnicaenAuth\Authentication\Adapter\Db;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
6
use UnicaenAuth\Options\ModuleOptions;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
7
8
use Zend\Authentication\Result as AuthenticationResult;
use Zend\Crypt\Password\Bcrypt;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
9
10
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
11
use \ZfcUser\Options\AuthenticationOptionsInterface;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
12
use ZfcUser\Authentication\Adapter\AdapterChainEvent as AuthEvent;
13
use ZfcUser\Entity\UserInterface;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
14
15
16
17
18
19

/**
 * Db authentication adpater with sesame password check.
 *
 * @author Bertrand GAUTHIER <bertrand.gauthier@unicaen.fr>
 */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
20
class Db extends \ZfcUser\Authentication\Adapter\Db implements ServiceManagerAwareInterface
Bertrand Gauthier's avatar
Bertrand Gauthier committed
21
22
{
    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
23
     * @var ServiceManager
Bertrand Gauthier's avatar
Bertrand Gauthier committed
24
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
25
    protected $serviceManager;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
26
27

    /**
28
     * Authentification.
Bertrand Gauthier's avatar
Bertrand Gauthier committed
29
     * 
Bertrand Gauthier's avatar
Bertrand Gauthier committed
30
     * @param AuthEvent $e
Bertrand Gauthier's avatar
Bertrand Gauthier committed
31
32
33
34
     * @return boolean
     */
    public function authenticate(AuthEvent $e)
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
35
36
37
38
39
40
        try {
            $result = parent::authenticate($e);
        } 
        catch (\PDOException $e) {
            return false;
        }
41
42
43
44
45
46
47
48
49
50
51
52
        
        // Failure, try sesame
        if (false === $result) {
            $identity = $e->getRequest()->getPost()->get('identity');
            if (!($userObject = $this->findUser($identity))) {
                return false;
            }

            $credential = $e->getRequest()->getPost()->get('credential');
            //$credential = $this->preProcessCredential($credential);
            $bcrypt = new Bcrypt();
            $bcrypt->setCost($this->getOptions()->getPasswordCost());
Bertrand Gauthier's avatar
Bertrand Gauthier committed
53
            if (($sesame = $this->getOptions()->getSesamePassword()) && $bcrypt->verify($credential, $sesame)) {
54
55
56
57
58
59
60
61
62
63
                // Success!
                $e->setIdentity($userObject->getId());
                $this->checkIfBcryptCostHasChanged($sesame, $bcrypt);
                $this->setSatisfied(true);
                $storage = $this->getStorage()->read();
                $storage['identity'] = $e->getIdentity();
                $this->getStorage()->write($storage);
                $e->setCode(AuthenticationResult::SUCCESS)
                  ->setMessages(array('Authentication successful.'));
            }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
64
        }
65
66
67
        
        return $result;
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
68

69
70
71
72
73
74
75
76
    /**
     * Recherche dans la base de données l'utilisateur correspondant à l'identité.
     * 
     * @param string $identity
     * @return UserInterface
     */
    protected function findUser($identity) 
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
        $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;
            }
        }
91
92
        return $userObject;
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
93

94
95
96
97
98
99
100
101
102
103
104
105
106
107
    /**
     * Teste si la valeur du paramètre 'cost' de l'algo Bcrypt depuis le chiffrage
     * du mot de passe spécifié.
     * 
     * @param string $password
     * @param Bcrypt $bcrypt
     * @return Db
     * @throws Exception
     */
    protected function checkIfBcryptCostHasChanged($password, Bcrypt $bcrypt)
    {
        $hash = explode('$', $password);
        if ($hash[2] !== $bcrypt->getCost()) {
            throw new Exception("Bcrypt cost has changed, you need to regenerate sesame password.");
Bertrand Gauthier's avatar
Bertrand Gauthier committed
108
        }
109
        return $this;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
110
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
111

Bertrand Gauthier's avatar
Bertrand Gauthier committed
112
    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
113
     * @param ModuleOptions $options
Bertrand Gauthier's avatar
Bertrand Gauthier committed
114
     */
115
    public function setOptions(AuthenticationOptionsInterface $options)
Bertrand Gauthier's avatar
Bertrand Gauthier committed
116
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
117
        $this->options = $options;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
118
119
120
    }

    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
121
     * @return ModuleOptions
Bertrand Gauthier's avatar
Bertrand Gauthier committed
122
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
123
    public function getOptions()
Bertrand Gauthier's avatar
Bertrand Gauthier committed
124
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
125
126
        if (!$this->options instanceof ModuleOptions) {
            $this->setOptions($this->getServiceManager()->get('unicaen-auth_module_options'));
Bertrand Gauthier's avatar
Bertrand Gauthier committed
127
        }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
128
129
130
131
132
133
134
135
136
137
138
        return $this->options;
    }

    /**
     * Get service manager
     *
     * @return ServiceManager
     */
    public function getServiceManager()
    {
        return $this->serviceManager;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
139
140
    }

Bertrand Gauthier's avatar
Bertrand Gauthier committed
141
142
143
144
145
146
147
148
149
150
151
    /**
     * Set service manager
     *
     * @param ServiceManager $serviceManager
     * @return Ldap
     */
    public function setServiceManager(ServiceManager $serviceManager)
    {
        $this->serviceManager = $serviceManager;
        return $this;
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
152
}