Translate failure messages of json authentication

This commit is contained in:
Malte Schlüter 2020-09-02 14:34:37 +02:00 committed by Fabien Potencier
parent 4ee85e8e3b
commit 7684663818
5 changed files with 40 additions and 3 deletions

View File

@ -143,6 +143,7 @@ return static function (ContainerConfigurator $container) {
abstract_arg('options'),
service('property_accessor')->nullOnInvalid(),
])
->call('setTranslator', [service('translator')->ignoreOnInvalid()])
->set('security.authenticator.remember_me', RememberMeAuthenticator::class)
->abstract()

View File

@ -189,6 +189,7 @@ return static function (ContainerConfigurator $container) {
service('event_dispatcher')->nullOnInvalid(),
service('property_accessor')->nullOnInvalid(),
])
->call('setTranslator', [service('translator')->ignoreOnInvalid()])
->tag('monolog.logger', ['channel' => 'security'])
->set('security.authentication.listener.remote_user', RemoteUserAuthenticationListener::class)

View File

@ -8,8 +8,9 @@ CHANGELOG
* Changed `AuthorizationChecker` to call the access decision manager in unauthenticated sessions with a `NullToken`
* [BC break] Removed `AccessListener::PUBLIC_ACCESS` in favor of `AuthenticatedVoter::PUBLIC_ACCESS`
* Added `Passport` to `LoginFailureEvent`.
* Deprecated `setProviderKey()`/`getProviderKey()` in favor of `setFirewallName()/getFirewallName()` in `PreAuthenticatedToken`, `RememberMeToken`, `SwitchUserToken`, `UsernamePasswordToken`, `DefaultAuthenticationSuccessHandler`; and deprecated the `AbstractRememberMeServices::$providerKey` property in favor of `AbstractRememberMeServices::$firewallName`
* Deprecated `setProviderKey()`/`getProviderKey()` in favor of `setFirewallName()/getFirewallName()` in `PreAuthenticatedToken`, `RememberMeToken`, `SwitchUserToken`, `UsernamePasswordToken`, `DefaultAuthenticationSuccessHandler`; and deprecated the `AbstractRememberMeServices::$providerKey` property in favor of `AbstractRememberMeServices::$firewallName`
* Added `FirewallListenerInterface` to make the execution order of firewall listeners configurable
* Added translator to `\Symfony\Component\Security\Http\Authenticator\JsonLoginAuthenticator` and `\Symfony\Component\Security\Http\Firewall\UsernamePasswordJsonAuthenticationListener` to translate authentication failure messages
5.1.0
-----

View File

@ -35,6 +35,7 @@ use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordC
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* Provides a stateless implementation of an authentication via
@ -55,6 +56,11 @@ class JsonLoginAuthenticator implements InteractiveAuthenticatorInterface
private $successHandler;
private $failureHandler;
/**
* @var TranslatorInterface|null
*/
private $translator;
public function __construct(HttpUtils $httpUtils, UserProviderInterface $userProvider, ?AuthenticationSuccessHandlerInterface $successHandler = null, ?AuthenticationFailureHandlerInterface $failureHandler = null, array $options = [], ?PropertyAccessorInterface $propertyAccessor = null)
{
$this->options = array_merge(['username_path' => 'username', 'password_path' => 'password'], $options);
@ -120,7 +126,13 @@ class JsonLoginAuthenticator implements InteractiveAuthenticatorInterface
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
if (null === $this->failureHandler) {
return new JsonResponse(['error' => $exception->getMessageKey()], JsonResponse::HTTP_UNAUTHORIZED);
$errorMessage = $exception->getMessageKey();
if (null !== $this->translator) {
$errorMessage = $this->translator->trans($exception->getMessageKey(), $exception->getMessageData(), 'security');
}
return new JsonResponse(['error' => $errorMessage], JsonResponse::HTTP_UNAUTHORIZED);
}
return $this->failureHandler->onAuthenticationFailure($request, $exception);
@ -131,6 +143,11 @@ class JsonLoginAuthenticator implements InteractiveAuthenticatorInterface
return true;
}
public function setTranslator(TranslatorInterface $translator)
{
$this->translator = $translator;
}
private function getCredentials(Request $request)
{
$data = json_decode($request->getContent());

View File

@ -34,6 +34,7 @@ use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* UsernamePasswordJsonAuthenticationListener is a stateless implementation of
@ -57,6 +58,11 @@ class UsernamePasswordJsonAuthenticationListener extends AbstractListener
private $propertyAccessor;
private $sessionStrategy;
/**
* @var TranslatorInterface|null
*/
private $translator;
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, HttpUtils $httpUtils, string $providerKey, AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, array $options = [], LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null, PropertyAccessorInterface $propertyAccessor = null)
{
$this->tokenStorage = $tokenStorage;
@ -182,7 +188,13 @@ class UsernamePasswordJsonAuthenticationListener extends AbstractListener
}
if (!$this->failureHandler) {
return new JsonResponse(['error' => $failed->getMessageKey()], 401);
$errorMessage = $failed->getMessageKey();
if (null !== $this->translator) {
$errorMessage = $this->translator->trans($failed->getMessageKey(), $failed->getMessageData(), 'security');
}
return new JsonResponse(['error' => $errorMessage], 401);
}
$response = $this->failureHandler->onAuthenticationFailure($request, $failed);
@ -204,6 +216,11 @@ class UsernamePasswordJsonAuthenticationListener extends AbstractListener
$this->sessionStrategy = $sessionStrategy;
}
public function setTranslator(TranslatorInterface $translator)
{
$this->translator = $translator;
}
private function migrateSession(Request $request, TokenInterface $token)
{
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {