Skip to content

Commit 74ca9f9

Browse files
wouterjchalasr
authored andcommitted
[Security] Rename UserInterface::getUsername() to getUserIdentifier()
1 parent b774505 commit 74ca9f9

29 files changed

+210
-109
lines changed

Authentication/AuthenticatorManager.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ public function __construct(iterable $authenticators, TokenStorageInterface $tok
7070
public function authenticateUser(UserInterface $user, AuthenticatorInterface $authenticator, Request $request, array $badges = []): ?Response
7171
{
7272
// create an authenticated token for the User
73-
$token = $authenticator->createAuthenticatedToken($passport = new SelfValidatingPassport(new UserBadge($user->getUsername(), function () use ($user) { return $user; }), $badges), $this->firewallName);
73+
// @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0
74+
$token = $authenticator->createAuthenticatedToken($passport = new SelfValidatingPassport(new UserBadge(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), function () use ($user) { return $user; }), $badges), $this->firewallName);
7475

7576
// announce the authenticated token
7677
$token = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($token))->getAuthenticatedToken();
@@ -215,6 +216,11 @@ private function executeAuthenticator(AuthenticatorInterface $authenticator, Req
215216

216217
private function handleAuthenticationSuccess(TokenInterface $authenticatedToken, PassportInterface $passport, Request $request, AuthenticatorInterface $authenticator): ?Response
217218
{
219+
// @deprecated since 5.3
220+
if (!method_exists($authenticatedToken->getUser(), 'getUserIdentifier')) {
221+
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "getUserIdentifier(): string" in user class "%s" is deprecated. This method will replace "getUsername()" in Symfony 6.0.', get_debug_type($authenticatedToken->getUser()));
222+
}
223+
218224
$this->tokenStorage->setToken($authenticatedToken);
219225

220226
$response = $authenticator->onAuthenticationSuccess($request, $authenticatedToken, $this->firewallName);

Authenticator/AbstractPreAuthenticatedAuthenticator.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,18 @@ public function supports(Request $request): ?bool
8787

8888
public function authenticate(Request $request): PassportInterface
8989
{
90-
return new SelfValidatingPassport(new UserBadge($request->attributes->get('_pre_authenticated_username'), function ($username) {
91-
return $this->userProvider->loadUserByUsername($username);
92-
}), [new PreAuthenticatedUserBadge()]);
90+
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
91+
$method = 'loadUserByIdentifier';
92+
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
93+
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
94+
95+
$method = 'loadUserByUsername';
96+
}
97+
98+
return new SelfValidatingPassport(
99+
new UserBadge($request->attributes->get('_pre_authenticated_username'), [$this->userProvider, $method]),
100+
[new PreAuthenticatedUserBadge()]
101+
);
93102
}
94103

95104
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface

Authenticator/AuthenticatorInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public function supports(Request $request): ?bool;
4646
* presented password and the CSRF token value.
4747
*
4848
* You may throw any AuthenticationException in this method in case of error (e.g.
49-
* a UsernameNotFoundException when the user cannot be found).
49+
* a UserNotFoundException when the user cannot be found).
5050
*
5151
* @throws AuthenticationException
5252
*/

Authenticator/FormLoginAuthenticator.php

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,19 @@ public function authenticate(Request $request): PassportInterface
8484
{
8585
$credentials = $this->getCredentials($request);
8686

87-
$passport = new Passport(new UserBadge($credentials['username'], function ($username) {
88-
$user = $this->userProvider->loadUserByUsername($username);
89-
if (!$user instanceof UserInterface) {
90-
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
91-
}
92-
93-
return $user;
94-
}), new PasswordCredentials($credentials['password']), [new RememberMeBadge()]);
87+
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
88+
$method = 'loadUserByIdentifier';
89+
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
90+
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
91+
92+
$method = 'loadUserByUsername';
93+
}
94+
95+
$passport = new Passport(
96+
new UserBadge($credentials['username'], [$this->userProvider, $method]),
97+
new PasswordCredentials($credentials['password']),
98+
[new RememberMeBadge()]
99+
);
95100
if ($this->options['enable_csrf']) {
96101
$passport->addBadge(new CsrfTokenBadge($this->options['csrf_token_id'], $credentials['csrf_token']));
97102
}

Authenticator/HttpBasicAuthenticator.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,18 @@ public function authenticate(Request $request): PassportInterface
6767
$username = $request->headers->get('PHP_AUTH_USER');
6868
$password = $request->headers->get('PHP_AUTH_PW', '');
6969

70-
$passport = new Passport(new UserBadge($username, function ($username) {
71-
$user = $this->userProvider->loadUserByUsername($username);
72-
if (!$user instanceof UserInterface) {
73-
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
74-
}
75-
76-
return $user;
77-
}), new PasswordCredentials($password));
70+
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
71+
$method = 'loadUserByIdentifier';
72+
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
73+
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
74+
75+
$method = 'loadUserByUsername';
76+
}
77+
78+
$passport = new Passport(
79+
new UserBadge($username, [$this->userProvider, $method]),
80+
new PasswordCredentials($password)
81+
);
7882
if ($this->userProvider instanceof PasswordUpgraderInterface) {
7983
$passport->addBadge(new PasswordUpgradeBadge($password, $this->userProvider));
8084
}

Authenticator/JsonLoginAuthenticator.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,18 @@ public function authenticate(Request $request): PassportInterface
9494
throw $e;
9595
}
9696

97-
$passport = new Passport(new UserBadge($credentials['username'], function ($username) {
98-
$user = $this->userProvider->loadUserByUsername($username);
99-
if (!$user instanceof UserInterface) {
100-
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
101-
}
97+
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
98+
$method = 'loadUserByIdentifier';
99+
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
100+
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
101+
102+
$method = 'loadUserByUsername';
103+
}
102104

103-
return $user;
104-
}), new PasswordCredentials($credentials['password']));
105+
$passport = new Passport(
106+
new UserBadge($credentials['username'], [$this->userProvider, $method]),
107+
new PasswordCredentials($credentials['password'])
108+
);
105109
if ($this->userProvider instanceof PasswordUpgraderInterface) {
106110
$passport->addBadge(new PasswordUpgradeBadge($credentials['password'], $this->userProvider));
107111
}

Authenticator/Passport/Badge/UserBadge.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace Symfony\Component\Security\Http\Authenticator\Passport\Badge;
1313

14-
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
14+
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
1515
use Symfony\Component\Security\Core\User\UserInterface;
1616
use Symfony\Component\Security\Http\EventListener\UserProviderListener;
1717

@@ -40,7 +40,7 @@ class UserBadge implements BadgeInterface
4040
* based on email *and* company name). This string can be used for e.g. login throttling.
4141
*
4242
* Optionally, you may pass a user loader. This callable receives the $userIdentifier
43-
* as argument and must return a UserInterface object (otherwise a UsernameNotFoundException
43+
* as argument and must return a UserInterface object (otherwise an AuthenticationServiceException
4444
* is thrown). If this is not set, the default user provider will be used with
4545
* $userIdentifier as username.
4646
*/
@@ -64,7 +64,7 @@ public function getUser(): UserInterface
6464

6565
$this->user = ($this->userLoader)($this->userIdentifier);
6666
if (!$this->user instanceof UserInterface) {
67-
throw new UsernameNotFoundException();
67+
throw new AuthenticationServiceException(sprintf('The user provider must return a UserInterface object, "%s" given.', \get_debug_type($this->user)));
6868
}
6969
}
7070

Authenticator/RememberMeAuthenticator.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ public function authenticate(Request $request): PassportInterface
8282
throw new \LogicException('No remember me token is set.');
8383
}
8484

85-
return new SelfValidatingPassport(new UserBadge($token->getUsername(), [$token, 'getUser']));
85+
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
86+
return new SelfValidatingPassport(new UserBadge(method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername(), [$token, 'getUser']));
8687
}
8788

8889
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface

EventListener/UserProviderListener.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ public function checkPassport(CheckPassportEvent $event): void
4646
return;
4747
}
4848

49-
$badge->setUserLoader([$this->userProvider, 'loadUserByUsername']);
49+
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
50+
if (method_exists($this->userProvider, 'loadUserByIdentifier')) {
51+
$badge->setUserLoader([$this->userProvider, 'loadUserByIdentifier']);
52+
} else {
53+
trigger_deprecation('symfony/security-http', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
54+
55+
$badge->setUserLoader([$this->userProvider, 'loadUserByUsername']);
56+
}
5057
}
5158
}

Firewall/AbstractAuthenticationListener.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ private function onFailure(Request $request, AuthenticationException $failed): R
195195
private function onSuccess(Request $request, TokenInterface $token): Response
196196
{
197197
if (null !== $this->logger) {
198-
$this->logger->info('User has been authenticated successfully.', ['username' => $token->getUsername()]);
198+
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
199+
$this->logger->info('User has been authenticated successfully.', ['username' => method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()]);
199200
}
200201

201202
$this->tokenStorage->setToken($token);

Firewall/AbstractPreAuthenticatedListener.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ public function authenticate(RequestEvent $event)
8383
}
8484

8585
if (null !== $token = $this->tokenStorage->getToken()) {
86-
if ($token instanceof PreAuthenticatedToken && $this->providerKey == $token->getFirewallName() && $token->isAuthenticated() && $token->getUsername() === $user) {
86+
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
87+
if ($token instanceof PreAuthenticatedToken && $this->providerKey == $token->getFirewallName() && $token->isAuthenticated() && (method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()) === $user) {
8788
return;
8889
}
8990
}

Firewall/BasicAuthenticationListener.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ public function authenticate(RequestEvent $event)
7373
}
7474

7575
if (null !== $token = $this->tokenStorage->getToken()) {
76-
if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $username) {
76+
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
77+
if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && (method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()) === $username) {
7778
return;
7879
}
7980
}

Firewall/ContextListener.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
2828
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
2929
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
30-
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
30+
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
3131
use Symfony\Component\Security\Core\User\UserInterface;
3232
use Symfony\Component\Security\Core\User\UserProviderInterface;
3333
use Symfony\Component\Security\Http\Event\DeauthenticatedEvent;
@@ -222,7 +222,8 @@ protected function refreshUser(TokenInterface $token): ?TokenInterface
222222
$userDeauthenticated = true;
223223

224224
if (null !== $this->logger) {
225-
$this->logger->debug('Cannot refresh token because user has changed.', ['username' => $refreshedUser->getUsername(), 'provider' => \get_class($provider)]);
225+
// @deprecated since 5.3, change to $refreshedUser->getUserIdentifier() in 6.0
226+
$this->logger->debug('Cannot refresh token because user has changed.', ['username' => method_exists($refreshedUser, 'getUserIdentifier') ? $refreshedUser->getUserIdentifier() : $refreshedUser->getUsername(), 'provider' => \get_class($provider)]);
226227
}
227228

228229
continue;
@@ -231,10 +232,12 @@ protected function refreshUser(TokenInterface $token): ?TokenInterface
231232
$token->setUser($refreshedUser);
232233

233234
if (null !== $this->logger) {
234-
$context = ['provider' => \get_class($provider), 'username' => $refreshedUser->getUsername()];
235+
// @deprecated since 5.3, change to $refreshedUser->getUserIdentifier() in 6.0
236+
$context = ['provider' => \get_class($provider), 'username' => method_exists($refreshedUser, 'getUserIdentifier') ? $refreshedUser->getUserIdentifier() : $refreshedUser->getUsername()];
235237

236238
if ($token instanceof SwitchUserToken) {
237-
$context['impersonator_username'] = $token->getOriginalToken()->getUsername();
239+
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
240+
$context['impersonator_username'] = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getOriginalToken()->getUsername();
238241
}
239242

240243
$this->logger->debug('User was reloaded from a user provider.', $context);
@@ -243,9 +246,9 @@ protected function refreshUser(TokenInterface $token): ?TokenInterface
243246
return $token;
244247
} catch (UnsupportedUserException $e) {
245248
// let's try the next user provider
246-
} catch (UsernameNotFoundException $e) {
249+
} catch (UserNotFoundException $e) {
247250
if (null !== $this->logger) {
248-
$this->logger->warning('Username could not be found in the selected user provider.', ['username' => $e->getUsername(), 'provider' => \get_class($provider)]);
251+
$this->logger->warning('Username could not be found in the selected user provider.', ['username' => method_exists($e, 'getUserIdentifier') ? $e->getUserIdentifier() : $e->getUsername(), 'provider' => \get_class($provider)]);
249252
}
250253

251254
$userNotFoundByProvider = true;

Firewall/SwitchUserListener.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,28 +140,36 @@ private function attemptSwitchUser(Request $request, string $username): ?TokenIn
140140
$originalToken = $this->getOriginalToken($token);
141141

142142
if (null !== $originalToken) {
143-
if ($token->getUsername() === $username) {
143+
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
144+
if ((method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()) === $username) {
144145
return $token;
145146
}
146147

147148
// User already switched, exit before seamlessly switching to another user
148149
$token = $this->attemptExitUser($request);
149150
}
150151

151-
$currentUsername = $token->getUsername();
152+
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
153+
$currentUsername = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
152154
$nonExistentUsername = '_'.md5(random_bytes(8).$username);
153155

154156
// To protect against user enumeration via timing measurements
155157
// we always load both successfully and unsuccessfully
158+
$methodName = 'loadUserByIdentifier';
159+
if (!method_exists($this->provider, $methodName)) {
160+
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->provider));
161+
162+
$methodName = 'loadUserByUsername';
163+
}
156164
try {
157-
$user = $this->provider->loadUserByUsername($username);
165+
$user = $this->provider->$methodName($username);
158166

159167
try {
160-
$this->provider->loadUserByUsername($nonExistentUsername);
168+
$this->provider->$methodName($nonExistentUsername);
161169
} catch (\Exception $e) {
162170
}
163171
} catch (AuthenticationException $e) {
164-
$this->provider->loadUserByUsername($currentUsername);
172+
$this->provider->$methodName($currentUsername);
165173

166174
throw $e;
167175
}

Firewall/UsernamePasswordJsonAuthenticationListener.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ public function authenticate(RequestEvent $event)
151151
private function onSuccess(Request $request, TokenInterface $token): ?Response
152152
{
153153
if (null !== $this->logger) {
154-
$this->logger->info('User has been authenticated successfully.', ['username' => $token->getUsername()]);
154+
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
155+
$this->logger->info('User has been authenticated successfully.', ['username' => method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()]);
155156
}
156157

157158
$this->migrateSession($request, $token);

0 commit comments

Comments
 (0)