1717use Symfony \Component \HttpKernel \Event \RequestEvent ;
1818use Symfony \Component \Security \Core \Authentication \AuthenticationManagerInterface ;
1919use Symfony \Component \Security \Core \Authentication \Token \TokenInterface ;
20+ use Symfony \Component \Security \Core \Exception \AccountStatusException ;
2021use Symfony \Component \Security \Core \Exception \AuthenticationException ;
22+ use Symfony \Component \Security \Core \Exception \BadCredentialsException ;
23+ use Symfony \Component \Security \Core \Exception \CustomUserMessageAccountStatusException ;
24+ use Symfony \Component \Security \Core \Exception \UsernameNotFoundException ;
2125use Symfony \Component \Security \Guard \AuthenticatorInterface ;
2226use Symfony \Component \Security \Guard \GuardAuthenticatorHandler ;
2327use Symfony \Component \Security \Guard \Token \PreAuthenticationGuardToken ;
@@ -40,12 +44,13 @@ class GuardAuthenticationListener extends AbstractListener
4044 private $ guardAuthenticators ;
4145 private $ logger ;
4246 private $ rememberMeServices ;
47+ private $ hideUserNotFoundExceptions ;
4348
4449 /**
4550 * @param string $providerKey The provider (i.e. firewall) key
4651 * @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
4752 */
48- public function __construct (GuardAuthenticatorHandler $ guardHandler , AuthenticationManagerInterface $ authenticationManager , string $ providerKey , iterable $ guardAuthenticators , LoggerInterface $ logger = null )
53+ public function __construct (GuardAuthenticatorHandler $ guardHandler , AuthenticationManagerInterface $ authenticationManager , string $ providerKey , iterable $ guardAuthenticators , LoggerInterface $ logger = null , bool $ hideUserNotFoundExceptions = true )
4954 {
5055 if (empty ($ providerKey )) {
5156 throw new \InvalidArgumentException ('$providerKey must not be empty. ' );
@@ -56,6 +61,7 @@ public function __construct(GuardAuthenticatorHandler $guardHandler, Authenticat
5661 $ this ->providerKey = $ providerKey ;
5762 $ this ->guardAuthenticators = $ guardAuthenticators ;
5863 $ this ->logger = $ logger ;
64+ $ this ->hideUserNotFoundExceptions = $ hideUserNotFoundExceptions ;
5965 }
6066
6167 /**
@@ -160,6 +166,12 @@ private function executeGuardAuthenticator(string $uniqueGuardKey, Authenticator
160166 $ this ->logger ->info ('Guard authentication failed. ' , ['exception ' => $ e , 'authenticator ' => \get_class ($ guardAuthenticator )]);
161167 }
162168
169+ // Avoid leaking error details in case of invalid user (e.g. user not found or invalid account status)
170+ // to prevent user enumeration via response content
171+ if ($ this ->hideUserNotFoundExceptions && ($ e instanceof UsernameNotFoundException || ($ e instanceof AccountStatusException && !$ e instanceof CustomUserMessageAccountStatusException))) {
172+ $ e = new BadCredentialsException ('Bad credentials. ' , 0 , $ e );
173+ }
174+
163175 $ response = $ this ->guardHandler ->handleAuthenticationFailure ($ e , $ request , $ guardAuthenticator , $ this ->providerKey );
164176
165177 if ($ response instanceof Response) {
0 commit comments