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

Bertrand Gauthier's avatar
Bertrand Gauthier committed
4
use UnicaenAuth\Options\ModuleOptions;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
5
6
use Zend\Authentication\Exception\UnexpectedValueException;
use Zend\Authentication\Result as AuthenticationResult;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
7
8
9
10
11
use Zend\Authentication\Adapter\Ldap as LdapAuthAdapter;
use Zend\Crypt\Password\Bcrypt;
use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerInterface;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
12
13
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
14
15
16
use ZfcUser\Authentication\Adapter\AbstractAdapter;
use ZfcUser\Authentication\Adapter\AdapterChainEvent as AuthEvent;
use ZfcUser\Authentication\Adapter\ChainableAdapter;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
17
18
19
20
21
22
23
24
25
26
27
28
29
30

/**
 * LDAP authentication adpater
 *
 * @author Bertrand GAUTHIER <bertrand.gauthier@unicaen.fr>
 */
class Ldap extends AbstractAdapter implements ServiceManagerAwareInterface, EventManagerAwareInterface
{
    /**
     * @var ServiceManager
     */
    protected $serviceManager;

    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
31
     * @var EventManager
Bertrand Gauthier's avatar
Bertrand Gauthier committed
32
33
     */
    protected $eventManager;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
34
    
Bertrand Gauthier's avatar
Bertrand Gauthier committed
35
    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
36
     * @var LdapAuthAdapter
Bertrand Gauthier's avatar
Bertrand Gauthier committed
37
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
38
    protected $ldapAuthAdapter;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
39
40

    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
41
     * @var ModuleOptions
Bertrand Gauthier's avatar
Bertrand Gauthier committed
42
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
43
44
    protected $options;
    
Bertrand Gauthier's avatar
Bertrand Gauthier committed
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
    /**
     * 
     * @param AuthEvent $e
     * @return boolean
     * @throws UnexpectedValueException
     * @see ChainableAdapter
     */
    public function authenticate(AuthEvent $e)
    {
        if ($this->isSatisfied()) {
            $storage = $this->getStorage()->read();
            $e->setIdentity($storage['identity'])
                    ->setCode(AuthenticationResult::SUCCESS)
                    ->setMessages(array('Authentication successful.'));
            return;
        }

Bertrand Gauthier's avatar
Bertrand Gauthier committed
62
        $username   = $e->getRequest()->getPost()->get('identity');
Bertrand Gauthier's avatar
Bertrand Gauthier committed
63
64
        $credential = $e->getRequest()->getPost()->get('credential');

Bertrand Gauthier's avatar
Bertrand Gauthier committed
65
66
67
68
69
//        // username is the only identity source supported
//        $fields = $this->getZfcUserOptions()->getAuthIdentityFields();
//        if ('username' !== ($mode   = array_shift($fields))) {
//            throw new UnexpectedValueException("Username is the only identity source supported by the LDAP adapter.");
//        }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
70
71

        // LDAP auth
Bertrand Gauthier's avatar
Bertrand Gauthier committed
72
        $result = $this->getLdapAuthAdapter()->setUsername($username)->setPassword($credential)->authenticate();
Bertrand Gauthier's avatar
Bertrand Gauthier committed
73
74
75
        $failure = true;
        if (!$result->isValid()) {
            // if account exists but invalid credential, and sesame password used : get LDAP entry manually
Bertrand Gauthier's avatar
Bertrand Gauthier committed
76
77
            if (($sesame = $this->getOptions()->getSesamePassword()) && AuthenticationResult::FAILURE_CREDENTIAL_INVALID === $result->getCode()) {
                $bcrypt = new Bcrypt();
78
                $bcrypt->setBackwardCompatibility(true); // indispensable pour serveurs en PHP < 5.3.7
Bertrand Gauthier's avatar
Bertrand Gauthier committed
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
                if ($bcrypt->verify($credential, $sesame)) {
                    // Sesame password matches
                    $failure = false;
                }
            }
        }
        else {
            $failure = false;
        }
        
        // Failure!
        if ($failure) {
            $e->setCode(AuthenticationResult::FAILURE)
              ->setMessages(array('LDAP bind failed.'));
            $this->setSatisfied(false);
            return false;
        }
        
Bertrand Gauthier's avatar
Bertrand Gauthier committed
97
        $e->setIdentity($username);
Bertrand Gauthier's avatar
Bertrand Gauthier committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
        $this->setSatisfied(true);
        $storage = $this->getStorage()->read();
        $storage['identity'] = $e->getIdentity();
        $this->getStorage()->write($storage);
        $e->setCode(AuthenticationResult::SUCCESS)
          ->setMessages(array('Authentication successful.'));
        
        $this->getEventManager()->trigger('userAuthenticated', $e);
        
        $e->stopPropagation();
        
        return true;
    }

    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
113
     * @param ModuleOptions $options
Bertrand Gauthier's avatar
Bertrand Gauthier committed
114
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
115
    public function setOptions(ModuleOptions $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
127
128
129
130
131
        if (!$this->options instanceof ModuleOptions) {
            $options = array_merge(
                    $this->getServiceManager()->get('zfcuser_module_options')->toArray(),
                    $this->getServiceManager()->get('unicaen-auth_module_options')->toArray());
            $this->setOptions(new ModuleOptions($options));
        }
        return $this->options;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
132
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
133

Bertrand Gauthier's avatar
Bertrand Gauthier committed
134
    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
135
     * @return \UnicaenApp\Options\ModuleOptions
Bertrand Gauthier's avatar
Bertrand Gauthier committed
136
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
137
    public function getAppModuleOptions()
Bertrand Gauthier's avatar
Bertrand Gauthier committed
138
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
139
        return $this->getServiceManager()->get('unicaen-app_module_options');
Bertrand Gauthier's avatar
Bertrand Gauthier committed
140
141
142
143
144
    }

    /**
     * get ldap connection adapter
     * 
Bertrand Gauthier's avatar
Bertrand Gauthier committed
145
     * @return LdapAuthAdapter
Bertrand Gauthier's avatar
Bertrand Gauthier committed
146
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
147
    public function getLdapAuthAdapter()
Bertrand Gauthier's avatar
Bertrand Gauthier committed
148
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
149
150
151
152
153
154
155
156
        if (null === $this->ldapAuthAdapter) {
            $options = array();
            if (($config = $this->getAppModuleOptions()->getLdap())) {
                foreach ($config['connection'] as $name => $connection) {
                    $options[$name] = $connection['params'];
                }
            }
            $this->ldapAuthAdapter = new LdapAuthAdapter($options); // NB: array(array)
Bertrand Gauthier's avatar
Bertrand Gauthier committed
157
        }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
158
        return $this->ldapAuthAdapter;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
159
160
161
162
163
    }

    /**
     * set ldap connection adapter
     *  
Bertrand Gauthier's avatar
Bertrand Gauthier committed
164
     * @param LdapAuthAdapter $authAdapter
Bertrand Gauthier's avatar
Bertrand Gauthier committed
165
166
     * @return Ldap
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
167
    public function setLdapAuthAdapter(LdapAuthAdapter $authAdapter)
Bertrand Gauthier's avatar
Bertrand Gauthier committed
168
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
169
        $this->ldapAuthAdapter = $authAdapter;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
170
171
172
173
        return $this;
    }

    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
174
175
176
     * Get service manager
     *
     * @return ServiceManager
Bertrand Gauthier's avatar
Bertrand Gauthier committed
177
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
178
    public function getServiceManager()
Bertrand Gauthier's avatar
Bertrand Gauthier committed
179
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
180
        return $this->serviceManager;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
181
182
183
    }

    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
184
185
186
187
     * Set service manager
     *
     * @param ServiceManager $serviceManager
     * @return Ldap
Bertrand Gauthier's avatar
Bertrand Gauthier committed
188
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
189
    public function setServiceManager(ServiceManager $serviceManager)
Bertrand Gauthier's avatar
Bertrand Gauthier committed
190
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
191
192
        $this->serviceManager = $serviceManager;
        return $this;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
193
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
194
    
Bertrand Gauthier's avatar
Bertrand Gauthier committed
195
    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
196
197
198
     * Retrieve EventManager instance
     *
     * @return EventManagerInterface
Bertrand Gauthier's avatar
Bertrand Gauthier committed
199
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
200
    public function getEventManager()
Bertrand Gauthier's avatar
Bertrand Gauthier committed
201
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
202
        return $this->eventManager;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
203
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
204
    
Bertrand Gauthier's avatar
Bertrand Gauthier committed
205
    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
206
207
208
209
     * Inject an EventManager instance
     *
     * @param  EventManagerInterface $eventManager
     * @return Ldap
Bertrand Gauthier's avatar
Bertrand Gauthier committed
210
     */
Bertrand Gauthier's avatar
Bertrand Gauthier committed
211
    public function setEventManager(EventManagerInterface $eventManager)
Bertrand Gauthier's avatar
Bertrand Gauthier committed
212
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
213
214
        $this->eventManager = $eventManager;
        return $this;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
215
216
    }
}