Some checks failed
Cadoles/hydra-sql/pipeline/pr-develop There was a failure building this commit
119 lines
4.8 KiB
PHP
119 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Security;
|
|
|
|
use App\Entity\User;
|
|
use App\Security\Hasher\PasswordEncoder;
|
|
use App\Service\SQLLoginService;
|
|
use App\SQLLogin\Exception\DataToFetchConfigurationException;
|
|
use App\SQLLogin\Exception\EmptyResultException;
|
|
use App\SQLLogin\Exception\InvalidSQLPasswordException;
|
|
use App\SQLLogin\Exception\SecurityPatternConfigurationException;
|
|
use App\SQLLogin\SQLLoginRequest;
|
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
|
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
|
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
|
use Symfony\Component\Security\Core\User\UserInterface;
|
|
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
|
|
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
|
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
|
use Symfony\Component\Security\Http\SecurityRequestAttributes;
|
|
|
|
class SQLLoginUserAuthenticator extends AbstractLoginFormAuthenticator
|
|
{
|
|
public const LOGIN_ROUTE = 'app_login';
|
|
public const ERROR_LOGIN = 'error_login';
|
|
public const TECHNICAL_ERROR = 'technical_error';
|
|
|
|
public function __construct(
|
|
private readonly string $baseUrl,
|
|
private readonly SQLLoginService $sqlLoginService,
|
|
private readonly PasswordEncoder $passwordHasher,
|
|
private readonly SQLLoginRequest $sqlLoginRequest
|
|
){
|
|
}
|
|
|
|
/**
|
|
* Called on every request to decide if this authenticator should be
|
|
* used for the request. Returning `false` will cause this authenticator
|
|
* to be skipped.
|
|
*/
|
|
public function supports(Request $request): bool
|
|
{
|
|
return self::LOGIN_ROUTE === $request->attributes->get('_route') && $request->isMethod('POST');
|
|
}
|
|
|
|
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey): RedirectResponse
|
|
{
|
|
return new RedirectResponse($this->baseUrl.'/connect/login-accept');
|
|
}
|
|
|
|
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): RedirectResponse
|
|
{
|
|
$request->getSession()->set(SecurityRequestAttributes::AUTHENTICATION_ERROR, $exception);
|
|
|
|
return new RedirectResponse($this->baseUrl.'/login');
|
|
}
|
|
|
|
public function authenticate(Request $request): SelfValidatingPassport
|
|
{
|
|
$form = $request->request->all(key: 'login');
|
|
$login = $form['login'];
|
|
$plaintextPassword = $form['password'];
|
|
$session = $request->getSession();
|
|
try {
|
|
$datas = $this->sqlLoginService->fetchPasswordAndDatas($login);
|
|
} catch (EmptyResultException $e) {
|
|
$session->set(self::ERROR_LOGIN, true);
|
|
throw new AuthenticationException();
|
|
} catch (DataToFetchConfigurationException|\PDOException $e) {
|
|
\Sentry\captureException($e);
|
|
$session->set(self::TECHNICAL_ERROR, true);
|
|
throw new AuthenticationException();
|
|
}
|
|
$remoteHashedPassword = $datas[$this->sqlLoginRequest->getPasswordColumnName()];
|
|
unset($datas[$this->sqlLoginRequest->getPasswordColumnName()]);
|
|
$remoteSalt = null;
|
|
if ($this->sqlLoginRequest->getSaltColumnName() && isset($datas[$this->sqlLoginRequest->getSaltColumnName()])) {
|
|
$remoteSalt = $datas[$this->sqlLoginRequest->getSaltColumnName()];
|
|
unset($datas[$this->sqlLoginRequest->getSaltColumnName()]);
|
|
}
|
|
if (null === $remoteHashedPassword) {
|
|
$remoteHashedPassword = '';
|
|
}
|
|
try {
|
|
// Comparaison remote hash et hash du input password + salt
|
|
$this->passwordHasher->verify($remoteHashedPassword, $plaintextPassword, $remoteSalt);
|
|
} catch (InvalidSQLPasswordException $e) {
|
|
$session->set(self::ERROR_LOGIN, true);
|
|
throw new AuthenticationException();
|
|
} catch (SecurityPatternConfigurationException $e) {
|
|
\Sentry\captureException($e);
|
|
$session->set(self::TECHNICAL_ERROR, true);
|
|
throw new AuthenticationException();
|
|
}
|
|
|
|
$user = new User($login, $remoteHashedPassword, $datas);
|
|
|
|
$loader = function (string $userIdentifier) use ($user): UserInterface {
|
|
if ($user->getLogin() !== $userIdentifier) {
|
|
throw new UserNotFoundException(sprintf('User "%s" not found.', $userIdentifier));
|
|
}
|
|
|
|
return $user;
|
|
};
|
|
|
|
$passport = new SelfValidatingPassport(new UserBadge($login, $loader));
|
|
$passport->setAttribute('attributes', $user->getAttributes());
|
|
|
|
return $passport;
|
|
}
|
|
|
|
protected function getLoginUrl(Request $request): string
|
|
{
|
|
return $this->baseUrl.'/login';
|
|
}
|
|
}
|