|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
/* |
|
6
|
|
|
* This file is part of Biurad opensource projects. |
|
7
|
|
|
* |
|
8
|
|
|
* PHP version 7.4 and above required |
|
9
|
|
|
* |
|
10
|
|
|
* @author Divine Niiquaye Ibok <[email protected]> |
|
11
|
|
|
* @copyright 2019 Biurad Group (https://biurad.com/) |
|
12
|
|
|
* @license https://opensource.org/licenses/BSD-3-Clause License |
|
13
|
|
|
* |
|
14
|
|
|
* For the full copyright and license information, please view the LICENSE |
|
15
|
|
|
* file that was distributed with this source code. |
|
16
|
|
|
* |
|
17
|
|
|
*/ |
|
18
|
|
|
|
|
19
|
|
|
namespace Biurad\Security\Authenticator; |
|
20
|
|
|
|
|
21
|
|
|
use Biurad\Security\Handler\RememberMeHandler; |
|
22
|
|
|
use Biurad\Security\Interfaces\AuthenticatorInterface; |
|
23
|
|
|
use Biurad\Security\Interfaces\RequireTokenInterface; |
|
24
|
|
|
use Psr\Http\Message\ServerRequestInterface; |
|
25
|
|
|
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface; |
|
26
|
|
|
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken; |
|
27
|
|
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; |
|
28
|
|
|
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; |
|
29
|
|
|
use Symfony\Component\Security\Core\Exception\AuthenticationException; |
|
30
|
|
|
use Symfony\Component\Security\Core\Exception\BadCredentialsException; |
|
31
|
|
|
use Symfony\Component\Security\Core\Security; |
|
32
|
|
|
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; |
|
33
|
|
|
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface; |
|
34
|
|
|
use Symfony\Component\Security\Core\User\UserProviderInterface; |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* This authenticator authenticates a user via form request. |
|
38
|
|
|
* |
|
39
|
|
|
* @author Divine Niiquaye Ibok <[email protected]> |
|
40
|
|
|
*/ |
|
41
|
|
|
class FormLoginAuthenticator implements AuthenticatorInterface, RequireTokenInterface |
|
42
|
|
|
{ |
|
43
|
|
|
private UserProviderInterface $provider; |
|
44
|
|
|
private ?TokenInterface $token = null; |
|
45
|
|
|
private PasswordHasherFactoryInterface $hasherFactory; |
|
46
|
|
|
private ?RememberMeHandler $rememberMeHandler; |
|
47
|
|
|
private string $userParameter, $passwordParameter; |
|
48
|
|
|
|
|
49
|
|
|
public function __construct( |
|
50
|
|
|
UserProviderInterface $provider, |
|
51
|
|
|
PasswordHasherFactoryInterface $hasherFactory, |
|
52
|
|
|
RememberMeHandler $rememberMeHandler = null, |
|
53
|
|
|
string $userParameter = '_identifier', |
|
54
|
|
|
string $passwordParameter = '_password' |
|
55
|
|
|
) { |
|
56
|
|
|
$this->provider = $provider; |
|
57
|
|
|
$this->hasherFactory = $hasherFactory; |
|
58
|
|
|
$this->rememberMeHandler = $rememberMeHandler; |
|
59
|
|
|
$this->userParameter = $userParameter; |
|
60
|
|
|
$this->passwordParameter = $passwordParameter; |
|
61
|
|
|
} |
|
62
|
|
|
|
|
63
|
|
|
/** |
|
64
|
|
|
* {@inheritdoc} |
|
65
|
|
|
*/ |
|
66
|
|
|
public function setToken(?TokenInterface $token): void |
|
67
|
|
|
{ |
|
68
|
|
|
$this->token = $token; |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* {@inheritdoc} |
|
73
|
|
|
*/ |
|
74
|
|
|
public function supports(ServerRequestInterface $request): bool |
|
75
|
|
|
{ |
|
76
|
|
|
return 'POST' === $request->getMethod(); |
|
77
|
|
|
} |
|
78
|
|
|
|
|
79
|
|
|
/** |
|
80
|
|
|
* {@inheritdoc} |
|
81
|
|
|
*/ |
|
82
|
|
|
public function authenticate(ServerRequestInterface $request, array $credentials, $firewallName): ?TokenInterface |
|
83
|
|
|
{ |
|
84
|
|
|
if (empty($credentials)) { |
|
85
|
|
|
return null; |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
$username = $credentials[$this->userParameter] ?? null; |
|
89
|
|
|
$password = $credentials[$this->passwordParameter] ?? null; |
|
90
|
|
|
|
|
91
|
|
|
if (empty($username) xor empty($password)) { |
|
92
|
|
|
throw new BadCredentialsException('The presented username or password cannot be empty.'); |
|
93
|
|
|
} |
|
94
|
|
|
|
|
95
|
|
|
if (!\is_string($username) || \strlen($username) > Security::MAX_USERNAME_LENGTH) { |
|
|
|
|
|
|
96
|
|
|
throw new BadCredentialsException('Invalid username.'); |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
$user = $this->provider->loadUserByIdentifier($username); |
|
100
|
|
|
|
|
101
|
|
|
if ($user instanceof PasswordAuthenticatedUserInterface) { |
|
102
|
|
|
$userHasher = $this->hasherFactory->getPasswordHasher($user); |
|
103
|
|
|
|
|
104
|
|
|
if (!$userHasher->verify($user->getPassword(), $password)) { |
|
|
|
|
|
|
105
|
|
|
throw new BadCredentialsException('The presented password is invalid.'); |
|
106
|
|
|
} |
|
107
|
|
|
|
|
108
|
|
|
if ($this->provider instanceof PasswordUpgraderInterface && $userHasher->needsRehash($password)) { |
|
|
|
|
|
|
109
|
|
|
$this->provider->upgradePassword($user, $userHasher->hash($password)); |
|
|
|
|
|
|
110
|
|
|
} |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
if ($request->hasHeader('X-Switch-User') && $oldToken = $this->token) { |
|
114
|
|
|
if ($username === $oldToken->getUserIdentifier()) { |
|
115
|
|
|
throw new AuthenticationException('The current user is already authenticated.'); |
|
116
|
|
|
} |
|
117
|
|
|
$token = new SwitchUserToken($user, $firewallName, $user->getRoles(), $oldToken, (string) $request->getUri()); |
|
118
|
|
|
} else { |
|
119
|
|
|
$token = new UsernamePasswordToken($user, $firewallName, $user->getRoles()); |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
if (null !== $this->rememberMeHandler) { |
|
123
|
|
|
$rememberMe = $credentials[$this->rememberMeHandler->getParameterName()] ?? false; |
|
124
|
|
|
|
|
125
|
|
|
if ('true' === $rememberMe || 'on' === $rememberMe || '1' === $rememberMe || 'yes' === $rememberMe || true === $rememberMe) { |
|
126
|
|
|
$rememberMeCookie = $this->rememberMeHandler->createRememberMeCookie($token->getUser()); |
|
|
|
|
|
|
127
|
|
|
$token->setAttribute(RememberMeHandler::REMEMBER_ME, $rememberMeCookie->withSecure('https' === $request->getUri()->getScheme())); |
|
128
|
|
|
} |
|
129
|
|
|
} |
|
130
|
|
|
|
|
131
|
|
|
return $token; |
|
132
|
|
|
} |
|
133
|
|
|
} |
|
134
|
|
|
|
This class constant has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.