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 \UsernameNotFoundException ;
21
24
use Symfony \Component \Security \Guard \AuthenticatorInterface ;
22
25
use Symfony \Component \Security \Guard \GuardAuthenticatorHandler ;
23
26
use Symfony \Component \Security \Guard \Token \PreAuthenticationGuardToken ;
@@ -44,12 +47,13 @@ class GuardAuthenticationListener extends AbstractListener implements ListenerIn
44
47
private $ guardAuthenticators ;
45
48
private $ logger ;
46
49
private $ rememberMeServices ;
50
+ private $ hideUserNotFoundExceptions ;
47
51
48
52
/**
49
53
* @param string $providerKey The provider (i.e. firewall) key
50
54
* @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
51
55
*/
52
- public function __construct (GuardAuthenticatorHandler $ guardHandler , AuthenticationManagerInterface $ authenticationManager , string $ providerKey , iterable $ guardAuthenticators , LoggerInterface $ logger = null )
56
+ public function __construct (GuardAuthenticatorHandler $ guardHandler , AuthenticationManagerInterface $ authenticationManager , string $ providerKey , iterable $ guardAuthenticators , LoggerInterface $ logger = null , bool $ hideUserNotFoundExceptions = true )
53
57
{
54
58
if (empty ($ providerKey )) {
55
59
throw new \InvalidArgumentException ('$providerKey must not be empty. ' );
@@ -60,6 +64,7 @@ public function __construct(GuardAuthenticatorHandler $guardHandler, Authenticat
60
64
$ this ->providerKey = $ providerKey ;
61
65
$ this ->guardAuthenticators = $ guardAuthenticators ;
62
66
$ this ->logger = $ logger ;
67
+ $ this ->hideUserNotFoundExceptions = $ hideUserNotFoundExceptions ;
63
68
}
64
69
65
70
/**
@@ -164,6 +169,12 @@ private function executeGuardAuthenticator(string $uniqueGuardKey, Authenticator
164
169
$ this ->logger ->info ('Guard authentication failed. ' , ['exception ' => $ e , 'authenticator ' => \get_class ($ guardAuthenticator )]);
165
170
}
166
171
172
+ // Avoid leaking error details in case of invalid user (e.g. user not found or invalid account status)
173
+ // to prevent user enumeration via response content
174
+ if ($ this ->hideUserNotFoundExceptions && ($ e instanceof UsernameNotFoundException || $ e instanceof AccountStatusException)) {
175
+ $ e = new BadCredentialsException ('Bad credentials. ' , 0 , $ e );
176
+ }
177
+
167
178
$ response = $ this ->guardHandler ->handleAuthenticationFailure ($ e , $ request , $ guardAuthenticator , $ this ->providerKey );
168
179
169
180
if ($ response instanceof Response) {
0 commit comments