Db.php 4.4 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;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
11
use ZfcUser\Authentication\Adapter\AdapterChainEvent as AuthEvent;
12
use ZfcUser\Entity\UserInterface;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
13
14
15
16
17
18

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

    /**
27
     * Authentification.
Bertrand Gauthier's avatar
Bertrand Gauthier committed
28
     * 
Bertrand Gauthier's avatar
Bertrand Gauthier committed
29
     * @param AuthEvent $e
Bertrand Gauthier's avatar
Bertrand Gauthier committed
30
31
32
33
     * @return boolean
     */
    public function authenticate(AuthEvent $e)
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
34
35
36
37
38
39
        try {
            $result = parent::authenticate($e);
        } 
        catch (\PDOException $e) {
            return false;
        }
40
41
42
43
44
45
46
47
48
49
50
51
        
        // 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
52
            if (($sesame = $this->getOptions()->getSesamePassword()) && $bcrypt->verify($credential, $sesame)) {
53
54
55
56
57
58
59
60
61
62
                // 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
63
        }
64
65
66
        
        return $result;
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
67

68
69
70
71
72
73
74
75
    /**
     * 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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
        $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;
            }
        }
90
91
        return $userObject;
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
    /**
     * 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
107
        }
108
        return $this;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
109
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
110

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

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

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

Bertrand Gauthier's avatar
Bertrand Gauthier committed
140
141
142
143
144
145
146
147
148
149
150
    /**
     * 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
151
}