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'), abstract_arg('options'),
service('property_accessor')->nullOnInvalid(), service('property_accessor')->nullOnInvalid(),
]) ])
->call('setTranslator', [service('translator')->ignoreOnInvalid()])
->set('security.authenticator.remember_me', RememberMeAuthenticator::class) ->set('security.authenticator.remember_me', RememberMeAuthenticator::class)
->abstract() ->abstract()

View File

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

View File

@ -10,6 +10,7 @@ CHANGELOG
* Added `Passport` to `LoginFailureEvent`. * 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 `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 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\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface; use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Contracts\Translation\TranslatorInterface;
/** /**
* Provides a stateless implementation of an authentication via * Provides a stateless implementation of an authentication via
@ -55,6 +56,11 @@ class JsonLoginAuthenticator implements InteractiveAuthenticatorInterface
private $successHandler; private $successHandler;
private $failureHandler; 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) 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); $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 public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{ {
if (null === $this->failureHandler) { 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); return $this->failureHandler->onAuthenticationFailure($request, $exception);
@ -131,6 +143,11 @@ class JsonLoginAuthenticator implements InteractiveAuthenticatorInterface
return true; return true;
} }
public function setTranslator(TranslatorInterface $translator)
{
$this->translator = $translator;
}
private function getCredentials(Request $request) private function getCredentials(Request $request)
{ {
$data = json_decode($request->getContent()); $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\SecurityEvents;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/** /**
* UsernamePasswordJsonAuthenticationListener is a stateless implementation of * UsernamePasswordJsonAuthenticationListener is a stateless implementation of
@ -57,6 +58,11 @@ class UsernamePasswordJsonAuthenticationListener extends AbstractListener
private $propertyAccessor; private $propertyAccessor;
private $sessionStrategy; 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) 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; $this->tokenStorage = $tokenStorage;
@ -182,7 +188,13 @@ class UsernamePasswordJsonAuthenticationListener extends AbstractListener
} }
if (!$this->failureHandler) { 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); $response = $this->failureHandler->onAuthenticationFailure($request, $failed);
@ -204,6 +216,11 @@ class UsernamePasswordJsonAuthenticationListener extends AbstractListener
$this->sessionStrategy = $sessionStrategy; $this->sessionStrategy = $sessionStrategy;
} }
public function setTranslator(TranslatorInterface $translator)
{
$this->translator = $translator;
}
private function migrateSession(Request $request, TokenInterface $token) private function migrateSession(Request $request, TokenInterface $token)
{ {
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) { if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {