17
17
use Symfony \Component \HttpKernel \Event \RequestEvent ;
18
18
use Symfony \Component \Security \Core \Authentication \AuthenticationManagerInterface ;
19
19
use Symfony \Component \Security \Core \Authentication \Token \TokenInterface ;
20
+ use Symfony \Component \Security \Core \Exception \AccountStatusException ;
20
21
use 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 ;
21
25
use Symfony \Component \Security \Guard \AuthenticatorInterface ;
22
26
use Symfony \Component \Security \Guard \GuardAuthenticatorHandler ;
23
27
use Symfony \Component \Security \Guard \Token \PreAuthenticationGuardToken ;
@@ -40,12 +44,13 @@ class GuardAuthenticationListener extends AbstractListener
40
44
private $ guardAuthenticators ;
41
45
private $ logger ;
42
46
private $ rememberMeServices ;
47
+ private $ hideUserNotFoundExceptions ;
43
48
44
49
/**
45
50
* @param string $providerKey The provider (i.e. firewall) key
46
51
* @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
47
52
*/
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 )
49
54
{
50
55
if (empty ($ providerKey )) {
51
56
throw new \InvalidArgumentException ('$providerKey must not be empty. ' );
@@ -56,6 +61,7 @@ public function __construct(GuardAuthenticatorHandler $guardHandler, Authenticat
56
61
$ this ->providerKey = $ providerKey ;
57
62
$ this ->guardAuthenticators = $ guardAuthenticators ;
58
63
$ this ->logger = $ logger ;
64
+ $ this ->hideUserNotFoundExceptions = $ hideUserNotFoundExceptions ;
59
65
}
60
66
61
67
/**
@@ -160,6 +166,12 @@ private function executeGuardAuthenticator(string $uniqueGuardKey, Authenticator
160
166
$ this ->logger ->info ('Guard authentication failed. ' , ['exception ' => $ e , 'authenticator ' => \get_class ($ guardAuthenticator )]);
161
167
}
162
168
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
+
163
175
$ response = $ this ->guardHandler ->handleAuthenticationFailure ($ e , $ request , $ guardAuthenticator , $ this ->providerKey );
164
176
165
177
if ($ response instanceof Response) {
0 commit comments