FormAuthenticator   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 15

Importance

Changes 0
Metric Value
wmc 21
c 0
b 0
f 0
lcom 2
cbo 15
dl 0
loc 149
rs 9.1666

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getCredentials() 0 16 4
A getUser() 0 8 2
D checkCredentials() 0 42 9
A onAuthenticationSuccess() 0 8 2
A onAuthenticationFailure() 0 6 1
A start() 0 5 1
A supportsRememberMe() 0 4 1
1
<?php
2
/*
3
  GESTCONV - Aplicación web para la gestión de la convivencia en centros educativos
4
5
  Copyright (C) 2015-2017: Luis Ramón López López
6
7
  This program is free software: you can redistribute it and/or modify
8
  it under the terms of the GNU Affero General Public License as published by
9
  the Free Software Foundation, either version 3 of the License, or
10
  (at your option) any later version.
11
12
  This program is distributed in the hope that it will be useful,
13
  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
  GNU Affero General Public License for more details.
16
17
  You should have received a copy of the GNU Affero General Public License
18
  along with this program.  If not, see [http://www.gnu.org/licenses/].
19
*/
20
21
namespace AppBundle\Security;
22
23
use AppBundle\Entity\Usuario;
24
use AppBundle\Service\SenecaAuthenticatorService;
25
use Doctrine\Common\Persistence\ManagerRegistry;
26
use Symfony\Component\HttpFoundation\RedirectResponse;
27
use Symfony\Component\HttpFoundation\Request;
28
use Symfony\Component\Routing\RouterInterface;
29
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
30
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
31
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
32
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
33
use Symfony\Component\Security\Core\Security;
34
use Symfony\Component\Security\Core\User\UserInterface;
35
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
36
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
37
use Symfony\Component\Security\Core\Exception\AuthenticationException;
38
use Symfony\Component\Security\Core\User\UserProviderInterface;
39
40
class FormAuthenticator extends AbstractGuardAuthenticator
41
{
42
    /**
43
     * @var UserPasswordEncoderInterface
44
     */
45
    private $encoder;
46
47
    /**
48
     * @var RouterInterface
49
     */
50
    private $router;
51
52
    /**
53
     * @var SenecaAuthenticatorService
54
     */
55
    private $senecaAuthenticator;
56
57
    /**
58
     * @var ManagerRegistry
59
     */
60
    private $managerRegistry;
61
62
    /**
63
     * Constructor
64
     */
65
    public function __construct(RouterInterface $router, UserPasswordEncoderInterface $encoder, SenecaAuthenticatorService $senecaAuthenticator, ManagerRegistry $managerRegistry) {
66
        $this->router = $router;
67
        $this->encoder = $encoder;
68
        $this->senecaAuthenticator = $senecaAuthenticator;
69
        $this->managerRegistry = $managerRegistry;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    public function getCredentials(Request $request)
76
    {
77
        $username = $request->request->get('_username');
78
        $session = $request->getSession();
79
80
        if ($request->attributes->get('_route') !== 'usuario_comprobar' || !$request->isMethod('POST') || !$session) {
81
            return null;
82
        }
83
84
        $session->set(Security::LAST_USERNAME, $username);
85
86
        return array(
87
            'username' => $username,
88
            'password' => $request->request->get('_password'),
89
        );
90
    }
91
92
    /**
93
     * {@inheritdoc}
94
     */
95
    public function getUser($credentials, UserProviderInterface $userProvider)
96
    {
97
        try {
98
            return $userProvider->loadUserByUsername($credentials['username']);
99
        } catch (UsernameNotFoundException $e) {
100
            throw new BadCredentialsException();
101
        }
102
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107
    public function checkCredentials($credentials, UserInterface $user)
108
    {
109
        if (!$user instanceof Usuario) {
110
            throw new AuthenticationServiceException();
111
        }
112
113
        $plainPassword = $credentials['password'];
114
115
        // ¿Comprobación de contraseña desde Séneca?
116
        if ($user->getEsExterno()) {
117
            $result = $this->senecaAuthenticator->checkUserCredentials($user->getUsername(), $plainPassword);
118
119
            if (SenecaAuthenticatorService::STATUS_USER_AUTHENTICATED === $result) {
120
                // contraseña correcta, actualizar en local por si perdemos la conectividad
121
                if (false === $this->encoder->isPasswordValid($user, $plainPassword)) {
122
                    $user->setPassword($this->encoder->encodePassword($user, $plainPassword));
123
                    $em = $this->managerRegistry->getManagerForClass('AppBundle\Entity\Usuario');
124
                    if ($em) {
125
                        $em->flush();
126
                    }
127
                }
128
                return true;
129
            }
130
131
            if (SenecaAuthenticatorService::STATUS_WRONG_USER_OR_PASSWORD === $result) {
132
                return false;
133
            }
134
135
            if (SenecaAuthenticatorService::STATUS_USER_BLOCKED === $result) {
136
                throw new \Symfony\Component\Security\Core\Exception\LockedException();
137
            }
138
139
            // si estamos aquí es que no se ha podido contactar con Séneca, intentar en local
140
        }
141
142
        // comprobación local
143
        if (false === $this->encoder->isPasswordValid($user, $plainPassword)) {
144
            throw new BadCredentialsException();
145
        }
146
147
        return true;
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
154
    {
155
        $targetPath = $request->getSession()->get('_security.'.$providerKey.'.target_path');
156
        if (!$targetPath) {
157
            $targetPath = $this->router->generate('portada');
158
        }
159
        return new RedirectResponse($targetPath);
160
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
166
    {
167
        $request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
168
        $url = $this->router->generate('usuario_entrar');
169
        return new RedirectResponse($url);
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175
    public function start(Request $request, AuthenticationException $authException = null)
176
    {
177
        $url = $this->router->generate('usuario_entrar');
178
        return new RedirectResponse($url);
179
    }
180
181
    /**
182
     * {@inheritdoc}
183
     */
184
    public function supportsRememberMe()
185
    {
186
        return false;
187
    }
188
}
189