Cas.php 8.25 KB
Newer Older
Bertrand Gauthier's avatar
Bertrand Gauthier committed
1
<?php
2

Bertrand Gauthier's avatar
Bertrand Gauthier committed
3
4
namespace UnicaenAuth\Authentication\Adapter;

5
use phpCAS;
6
use UnicaenApp\Mapper\Ldap\People as LdapPeopleMapper;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
7
use UnicaenAuth\Options\ModuleOptions;
8
use UnicaenAuth\Service\User;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
9
10
use Zend\Authentication\Exception\UnexpectedValueException;
use Zend\Authentication\Result as AuthenticationResult;
11
use Zend\EventManager\Event;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
12
13
14
use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerInterface;
15
use Zend\Router\Http\TreeRouteStack;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
16
use ZfcUser\Authentication\Adapter\AbstractAdapter;
17
use ZfcUser\Authentication\Adapter\AdapterChainEvent;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
18
use ZfcUser\Authentication\Adapter\ChainableAdapter;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
19
20
21
22
23
24

/**
 * CAS authentication adpater
 *
 * @author Bertrand GAUTHIER <bertrand.gauthier@unicaen.fr>
 */
25
class Cas extends AbstractAdapter implements EventManagerAwareInterface
Bertrand Gauthier's avatar
Bertrand Gauthier committed
26
{
Bertrand Gauthier's avatar
Bertrand Gauthier committed
27
28
29
30
    /**
     * @var EventManager
     */
    protected $eventManager;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
31

Bertrand Gauthier's avatar
Bertrand Gauthier committed
32
33
34
35
    /**
     * @var ModuleOptions
     */
    protected $options;
36
37
38
39
40
41
42
43
44
45

    /**
     * @var array
     */
    protected $casOptions;

    /**
     * @var phpCAS
     */
    protected $casClient;
46

47
48
49
50
51
    /**
     * @var LdapPeopleMapper
     */
    protected $ldapPeopleMapper;

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
    /**
     * @var User
     */
    private $userService;

    /**
     * @param User $userService
     */
    public function setUserService(User $userService)
    {
        $this->userService = $userService;
    }

    /**
     * @var TreeRouteStack
     */
    private $router;

    /**
     * @param TreeRouteStack $router
     */
    public function setRouter(TreeRouteStack $router)
    {
        $this->router = $router;
    }

Bertrand Gauthier's avatar
Bertrand Gauthier committed
78
    /**
79
     * Réalise l'authentification.
80
     *
81
     * @param AdapterChainEvent $e
Bertrand Gauthier's avatar
Bertrand Gauthier committed
82
83
84
     * @throws UnexpectedValueException
     * @see ChainableAdapter
     */
85
    public function authenticate(AdapterChainEvent $e)
Bertrand Gauthier's avatar
Bertrand Gauthier committed
86
    {
87
88
89
90
91
92
93
94
//        if ($e->getIdentity()) {
//            return;
//        }
	/* DS : modification liée à une boucle infinie lors de l'authentification CAS */
	if ($this->isSatisfied()) {
            $storage = $this->getStorage()->read();
            $e->setIdentity($storage['identity'])
                    ->setCode(AuthenticationResult::SUCCESS)
95
                    ->setMessages(['Authentication successful.']);
96
97
            return;
        }
98

Bertrand Gauthier's avatar
Bertrand Gauthier committed
99
100
101
102
        $config = $this->getOptions()->getCas();
        if (!$config) {
            return; // NB: l'authentification CAS est désactivée ssi le tableau des options est vide
        }
103

Bertrand Gauthier's avatar
Bertrand Gauthier committed
104
105
        error_reporting($oldErrorReporting = error_reporting() & ~E_NOTICE);

106
        $this->getCasClient()->forceAuthentication();
Bertrand Gauthier's avatar
Bertrand Gauthier committed
107
108
109
110

        // at this step, the user has been authenticated by the CAS server
        // and the user's login name can be read with phpCAS::getUser().

111
        $identity = $this->getCasClient(false)->getUser();
112

Bertrand Gauthier's avatar
Bertrand Gauthier committed
113
        error_reporting($oldErrorReporting);
114

Bertrand Gauthier's avatar
Bertrand Gauthier committed
115
116
117
118
119
120
        $e->setIdentity($identity);
        $this->setSatisfied(true);
        $storage = $this->getStorage()->read();
        $storage['identity'] = $e->getIdentity();
        $this->getStorage()->write($storage);
        $e->setCode(AuthenticationResult::SUCCESS)
121
122
          ->setMessages(['Authentication successful.']);

123
124
125
126
        // recherche de l'individu dans l'annuaire LDAP (il existe forcément puisque l'auth CAS a réussi)
        $ldapPeople = $this->getLdapPeopleMapper()->findOneByUsername($identity);

        /* @var $userService User */
127
        $this->userService->userAuthenticated($ldapPeople);
Bertrand Gauthier's avatar
Bertrand Gauthier committed
128
    }
129

130
    /**
131
     *
132
     * @param Event $e
133
134
     * @see ChainableAdapter
     */
135
    public function logout(Event $e)
136
137
138
139
    {
        if (!$this->getOptions()->getCas()) {
            return; // NB: l'authentification CAS est désactivée ssi le tableau des options est vide
        }
140

141
        $returnUrl = $this->router->getRequestUri()->setPath($this->router->getBaseUrl())->toString();
142
        $this->getCasClient()->logoutWithRedirectService($returnUrl);
143
    }
144

145
    /**
146
     * Retourne le client CAS.
147
     *
148
149
150
     * @param boolean $initClient
     * @return phpCAS
     * @throws Exception
151
     */
152
    public function getCasClient($initClient = true)
153
    {
154
155
        if (null === $this->casClient) {
            $this->casClient = new phpCAS();
156
        }
157

158
159
160
        if (!$initClient) {
            return $this->casClient;
        }
161

162
163
164
165
166
167
168
        if (null === $this->casOptions) {
            $config = $this->getOptions()->getCas();
            if (!isset($config['connection']['default']['params']) || !$config['connection']['default']['params']) {
                throw new Exception("Les paramètres de connexion au serveur CAS sont invalides.");
            }
            $this->casOptions = $config['connection']['default']['params'];
        }
169

170
        $options = $this->casOptions;
171

172
        if (array_key_exists('debug', $options) && (bool) $options['debug']) {
173
            $this->casClient->setDebug();
174
        }
175

176
        // initialize phpCAS
177
        $this->casClient->client($options['version'], $options['hostname'], $options['port'], $options['uri'], true);
178
        // no SSL validation for the CAS server
179
        $this->casClient->setNoCasServerValidation();
180

181
182
        return $this->casClient;
    }
183

184
185
    /**
     * Spécifie le client CAS.
186
     *
187
188
189
190
191
192
193
     * @param phpCAS $casClient
     * @return self
     */
    public function setCasClient(phpCAS $casClient)
    {
        $this->casClient = $casClient;
        return $this;
194
    }
195

Bertrand Gauthier's avatar
Bertrand Gauthier committed
196
197
198
199
200
201
202
203
204
205
206
207
208
    /**
     * @param ModuleOptions $options
     */
    public function setOptions(ModuleOptions $options)
    {
        $this->options = $options;
    }

    /**
     * @return ModuleOptions
     */
    public function getOptions()
    {
209
210
211
212
213
214
//        if (!$this->options instanceof ModuleOptions) {
//            $options = array_merge(
//                    $this->serviceLocator->get('zfcuser_module_options')->toArray(),
//                    $this->serviceLocator->get('unicaen-auth_module_options')->toArray());
//            $this->setOptions(new ModuleOptions($options));
//        }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
215
216
217
        return $this->options;
    }

218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
    /**
     * get ldap people mapper
     *
     * @return LdapPeopleMapper
     */
    public function getLdapPeopleMapper()
    {
        return $this->ldapPeopleMapper;
    }

    /**
     * set ldap people mapper
     *
     * @param LdapPeopleMapper $mapper
     * @return self
     */
    public function setLdapPeopleMapper(LdapPeopleMapper $mapper)
    {
        $this->ldapPeopleMapper = $mapper;
237

238
239
240
        return $this;
    }

Bertrand Gauthier's avatar
Bertrand Gauthier committed
241
242
243
244
245
246
247
248
249
    /**
     * Retrieve EventManager instance
     *
     * @return EventManagerInterface
     */
    public function getEventManager()
    {
        return $this->eventManager;
    }
250

Bertrand Gauthier's avatar
Bertrand Gauthier committed
251
    /**
252
     * {@inheritdoc}
Bertrand Gauthier's avatar
Bertrand Gauthier committed
253
254
255
256
257
258
     */
    public function setEventManager(EventManagerInterface $eventManager)
    {
        $this->eventManager = $eventManager;
        return $this;
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302

    /**
     * @param TreeRouteStack $router
     */
    public function reconfigureRoutesForCasAuth(TreeRouteStack $router)
    {
        $router->addRoutes([
            // remplace les routes existantes (cf. config du module)
            'zfcuser' => [
                'type'          => 'Literal',
                'priority'      => 1000,
                'options'       => [
                    'route'    => '/auth',
                    'defaults' => [
                        'controller' => 'zfcuser',
                        'action'     => 'index',
                    ],
                ],
                'may_terminate' => true,
                'child_routes'  => [
                    'login'  => [
                        'type'    => 'Literal',
                        'options' => [
                            'route'    => '/connexion',
                            'defaults' => [
                                'controller' => 'zfcuser',
                                'action'     => 'authenticate', // zappe l'action 'login'
                            ],
                        ],
                    ],
                    'logout' => [
                        'type'    => 'Literal',
                        'options' => [
                            'route'    => '/deconnexion',
                            'defaults' => [
                                'controller' => 'zfcuser',
                                'action'     => 'logout',
                            ],
                        ],
                    ],
                ],
            ],
        ]);
    }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
303
}