LoginFormAuthenticator   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 38
dl 0
loc 89
rs 10
c 0
b 0
f 0
wmc 14

7 Methods

Rating   Name   Duplication   Size   Complexity  
A onAuthenticationSuccess() 0 8 2
A getLoginUrl() 0 3 1
A getUser() 0 20 4
A getCredentials() 0 13 1
A checkCredentials() 0 14 3
A __construct() 0 6 1
A supports() 0 4 2
1
<?php
2
3
namespace App\Security;
4
5
use App\Entity\User;
6
use App\Exception\RedirectException;
7
use Doctrine\ORM\EntityManagerInterface;
8
use Symfony\Component\HttpFoundation\RedirectResponse;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
11
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
12
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
13
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
14
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
15
use Symfony\Component\Security\Core\Security;
16
use Symfony\Component\Security\Core\User\UserInterface;
17
use Symfony\Component\Security\Core\User\UserProviderInterface;
18
use Symfony\Component\Security\Csrf\CsrfToken;
19
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
20
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
21
use Symfony\Component\Security\Http\Util\TargetPathTrait;
22
23
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
24
{
25
    use TargetPathTrait;
26
27
    private $entityManager;
28
    private $urlGenerator;
29
    private $csrfTokenManager;
30
    private $passwordEncoder;
31
32
    public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder)
33
    {
34
        $this->entityManager = $entityManager;
35
        $this->urlGenerator = $urlGenerator;
36
        $this->csrfTokenManager = $csrfTokenManager;
37
        $this->passwordEncoder = $passwordEncoder;
38
    }
39
40
    public function supports(Request $request)
41
    {
42
        return 'app_login' === $request->attributes->get('_route')
43
            && $request->isMethod('POST');
44
    }
45
46
    public function getCredentials(Request $request)
47
    {
48
        $credentials = [
49
            'email' => $request->request->get('email'),
50
            'password' => $request->request->get('password'),
51
            'csrf_token' => $request->request->get('_csrf_token'),
52
        ];
53
        $request->getSession()->set(
54
            Security::LAST_USERNAME,
55
            $credentials['email']
56
        );
57
58
        return $credentials;
59
    }
60
61
    public function getUser($credentials, UserProviderInterface $userProvider)
62
    {
63
        $token = new CsrfToken('authenticate', $credentials['csrf_token']);
64
        if (!$this->csrfTokenManager->isTokenValid($token)) {
65
            throw new InvalidCsrfTokenException();
66
        }
67
68
        $user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $credentials['email']]);
69
70
        if (!$user) {
71
            //try with userName
72
            $user = $this->entityManager->getRepository(User::class)->findOneBy(['userName' => $credentials['email']]);
73
            if (!$user) {
74
                // fail authentication with a custom error
75
                throw new CustomUserMessageAuthenticationException('Email or username could not be found.');
76
            }
77
78
        }
79
80
        return $user;
81
    }
82
83
    public function checkCredentials($credentials, UserInterface $user)
84
    {
85
        //is user and pass valid
86
        if (!$this->passwordEncoder->isPasswordValid($user, $credentials['password'])) {
87
            return false;
88
        }
89
90
        //is account email verified
91
        if (!$user->getVerified()) {
0 ignored issues
show
Bug introduced by
The method getVerified() does not exist on Symfony\Component\Security\Core\User\UserInterface. It seems like you code against a sub-type of Symfony\Component\Security\Core\User\UserInterface such as App\Entity\User. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

91
        if (!$user->/** @scrutinizer ignore-call */ getVerified()) {
Loading history...
92
            throw new RedirectException($this->urlGenerator->generate('app_forgotpassword'), 'account is not verified');
93
        }
94
95
        //If we get here then all is good
96
        return true;
97
    }
98
99
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
100
    {
101
        if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
0 ignored issues
show
Bug introduced by
It seems like $request->getSession() can also be of type null; however, parameter $session of App\Security\LoginFormAu...icator::getTargetPath() does only seem to accept Symfony\Component\HttpFo...ession\SessionInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
        if ($targetPath = $this->getTargetPath(/** @scrutinizer ignore-type */ $request->getSession(), $providerKey)) {
Loading history...
102
            return new RedirectResponse($targetPath);
103
        }
104
105
        // by default, return to the profile page
106
        return new RedirectResponse($this->urlGenerator->generate('home'));
107
    }
108
109
    protected function getLoginUrl()
110
    {
111
        return $this->urlGenerator->generate('app_login');
112
    }
113
}
114