Completed
Push — master ( 3e31ed...54e145 )
by Artem
03:34
created

AbstractAuthenticator::onAuthenticationSuccess()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 7
cts 7
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 3
crap 2
1
<?php
2
3
//----------------------------------------------------------------------
4
//
5
//  Copyright (C) 2017 Artem Rodygin
6
//
7
//  You should have received a copy of the MIT License along with
8
//  this file. If not, see <http://opensource.org/licenses/MIT>.
9
//
10
//----------------------------------------------------------------------
11
12
namespace Pignus\Authenticator;
13
14
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
15
use Symfony\Component\HttpFoundation\JsonResponse;
16
use Symfony\Component\HttpFoundation\RedirectResponse;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\HttpFoundation\Session\SessionInterface;
20
use Symfony\Component\Routing\RouterInterface;
21
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
22
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
23
use Symfony\Component\Security\Core\Exception\AuthenticationException;
24
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
25
use Symfony\Component\Security\Core\Security;
26
use Symfony\Component\Security\Core\User\UserInterface;
27
use Symfony\Component\Security\Core\User\UserProviderInterface;
28
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
29
30
/**
31
 * Authenticates user against the database.
32
 */
33
abstract class AbstractAuthenticator extends AbstractGuardAuthenticator
34
{
35
    protected $router;
36
    protected $session;
37
    protected $encoders;
38
    protected $firewalls;
39
40
    /**
41
     * Dependency Injection constructor.
42
     *
43
     * @param RouterInterface         $router
44
     * @param SessionInterface        $session
45
     * @param EncoderFactoryInterface $encoders
46
     * @param FirewallMap             $firewalls
47
     */
48 13
    public function __construct(
49
        RouterInterface         $router,
50
        SessionInterface        $session,
51
        EncoderFactoryInterface $encoders,
52
        FirewallMap             $firewalls)
53
    {
54 13
        $this->router    = $router;
55 13
        $this->session   = $session;
56 13
        $this->encoders  = $encoders;
57 13
        $this->firewalls = $firewalls;
58 13
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 4
    public function start(Request $request, AuthenticationException $authException = null)
64
    {
65
        // Do not redirect the user if it's an AJAX request.
66 4
        if ($request->isXmlHttpRequest()) {
67
68 2
            $exception = $this->session->get(Security::AUTHENTICATION_ERROR);
69 2
            $this->session->remove(Security::AUTHENTICATION_ERROR);
70
71 2
            $message = $exception === null
72 1
                ? 'Authentication required.'
73 2
                : $exception->getMessage();
74
75 2
            return new Response($message, Response::HTTP_UNAUTHORIZED);
76
        }
77
78 2
        $firewall = $this->firewalls->getFirewallConfig($request)->getName();
79
80 2
        return new RedirectResponse($this->getLoginUrl($this->router, $firewall));
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 2
    public function getCredentials(Request $request)
87
    {
88 2
        if (!$request->request->has('_username')) {
89 1
            return null;
90
        }
91
92
        return [
93 1
            'username' => $request->request->get('_username'),
94 1
            'password' => $request->request->get('_password'),
95
        ];
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101 2
    public function getUser($credentials, UserProviderInterface $userProvider)
102
    {
103
        try {
104 2
            return $userProvider->loadUserByUsername($credentials['username']);
105
        }
106 1
        catch (UsernameNotFoundException $e) {
107 1
            throw new AuthenticationException('Bad credentials.');
108
        }
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114 2
    public function checkCredentials($credentials, UserInterface $user)
115
    {
116 2
        $encoder = $this->encoders->getEncoder(get_class($user));
117
118 2
        if (!$encoder->isPasswordValid($user->getPassword(), $credentials['password'], $user->getSalt())) {
119 1
            throw new AuthenticationException('Bad credentials.');
120
        }
121
122 1
        return true;
123
    }
124
125
    /**
126
     * {@inheritdoc}
127
     */
128 2
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
129
    {
130 2
        $this->session->remove(Security::AUTHENTICATION_ERROR);
131
132
        // An URL the user was trying to reach before authentication.
133 2
        $targetPath = sprintf('_security.%s.target_path', $providerKey);
134 2
        $targetUrl  = $this->session->get($targetPath, $this->getDefaultUrl($this->router, $providerKey));
135
136
        // Do not redirect the user if it's an AJAX request.
137 2
        return $request->isXmlHttpRequest()
138 1
            ? new JsonResponse()
139 2
            : new RedirectResponse($targetUrl);
140
    }
141
142
    /**
143
     * {@inheritdoc}
144
     */
145 2
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
146
    {
147 2
        $this->session->set(Security::AUTHENTICATION_ERROR, $exception);
148
149 2
        return $this->start($request, $exception);
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155 1
    public function supportsRememberMe()
156
    {
157 1
        return true;
158
    }
159
160
    /**
161
     * Returns URL to login page of the specified firewall.
162
     *
163
     * @param RouterInterface $router
164
     * @param string          $firewall
165
     *
166
     * @return string
167
     */
168
    abstract protected function getLoginUrl(RouterInterface $router, string $firewall): string;
169
170
    /**
171
     * Returns URL to default page of the specified firewall.
172
     *
173
     * @param RouterInterface $router
174
     * @param string          $firewall
175
     *
176
     * @return string
177
     */
178
    abstract protected function getDefaultUrl(RouterInterface $router, string $firewall): string;
179
}
180