diff --git a/controller/argument_value_resolver.rst b/controller/argument_value_resolver.rst index c9693bbaf9b..ebc59a02bf5 100644 --- a/controller/argument_value_resolver.rst +++ b/controller/argument_value_resolver.rst @@ -75,7 +75,7 @@ with the ``User`` class:: { public function index(User $user) { - return new Response('Hello '.$user->getUsername().'!'); + return new Response('Hello '.$user->getUserIdentifier().'!'); } } diff --git a/reference/configuration/security.rst b/reference/configuration/security.rst index 053ff55e300..630c65879f1 100644 --- a/reference/configuration/security.rst +++ b/reference/configuration/security.rst @@ -89,8 +89,8 @@ If ``true``, when a user is not found a generic exception of type is thrown with the message "Bad credentials". If ``false``, the exception thrown is of type -:class:`Symfony\\Component\\Security\\Core\\Exception\\UsernameNotFoundException` -and it includes the given not found username. +:class:`Symfony\\Component\\Security\\Core\\Exception\\UserNotFoundException` +and it includes the given not found user identifier. session_fixation_strategy ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/routing.rst b/routing.rst index 191e255aab6..641d4e43b2f 100644 --- a/routing.rst +++ b/routing.rst @@ -2402,7 +2402,7 @@ use the ``generateUrl()`` helper:: // generate a URL with route arguments $userProfilePage = $this->generateUrl('user_profile', [ - 'username' => $user->getUsername(), + 'username' => $user->getUserIdentifier(), ]); // generated URLs are "absolute paths" by default. Pass a third optional @@ -2472,7 +2472,7 @@ the :class:`Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface` class // generate a URL with route arguments $userProfilePage = $this->router->generate('user_profile', [ - 'username' => $user->getUsername(), + 'username' => $user->getUserIdentifier(), ]); // generated URLs are "absolute paths" by default. Pass a third optional @@ -2595,7 +2595,7 @@ Now you'll get the expected results when generating URLs in your commands:: // generate a URL with route arguments $userProfilePage = $this->router->generate('user_profile', [ - 'username' => $user->getUsername(), + 'username' => $user->getUserIdentifier(), ]); // generated URLs are "absolute paths" by default. Pass a third optional diff --git a/security/custom_authentication_provider.rst b/security/custom_authentication_provider.rst index a638169f4f0..04c94a4a82c 100644 --- a/security/custom_authentication_provider.rst +++ b/security/custom_authentication_provider.rst @@ -218,7 +218,10 @@ the ``PasswordDigest`` header value matches with the user's password:: public function authenticate(TokenInterface $token): WsseUserToken { - $user = $this->userProvider->loadUserByUsername($token->getUsername()); + // The loadUserByIdentifier() and getUserIdentifier() methods were + // introduced in Symfony 5.3. In previous versions they were called + // loadUserByUsername() and getUsername() respectively + $user = $this->userProvider->loadUserByIdentifier($token->getUserIdentifier()); if ($user && $this->validateDigest($token->digest, $token->nonce, $token->created, $user->getPassword())) { $authenticatedToken = new WsseUserToken($user->getRoles()); diff --git a/security/experimental_authenticators.rst b/security/experimental_authenticators.rst index b7734ef88e0..b35dbd79559 100644 --- a/security/experimental_authenticators.rst +++ b/security/experimental_authenticators.rst @@ -456,7 +456,7 @@ using :ref:`the user provider `:: You can optionally pass a user loader as second argument to the ``UserBadge``. This callable receives the ``$userIdentifier`` and must return a ``UserInterface`` object (otherwise a - ``UsernameNotFoundException`` is thrown):: + ``UserNotFoundException`` is thrown):: // src/Security/CustomAuthenticator.php namespace App\Security; diff --git a/security/guard_authentication.rst b/security/guard_authentication.rst index ebd1c2471ce..7108ba0906e 100644 --- a/security/guard_authentication.rst +++ b/security/guard_authentication.rst @@ -172,10 +172,10 @@ This requires you to implement several methods:: return null; } - // The "username" in this case is the apiToken, see the key `property` + // The user identifier in this case is the apiToken, see the key `property` // of `your_db_provider` in `security.yaml`. // If this returns a user, checkCredentials() is called next: - return $userProvider->loadUserByUsername($credentials); + return $userProvider->loadUserByIdentifier($credentials); } public function checkCredentials($credentials, UserInterface $user): bool diff --git a/security/json_login_setup.rst b/security/json_login_setup.rst index 6758a3917ef..41107f9f46a 100644 --- a/security/json_login_setup.rst +++ b/security/json_login_setup.rst @@ -85,7 +85,9 @@ The next step is to configure a route in your app matching this path: $user = $this->getUser(); return $this->json([ - 'username' => $user->getUsername(), + // The getUserIdentifier() method was introduced in Symfony 5.3. + // In previous versions it was called getUsername() + 'username' => $user->getUserIdentifier(), 'roles' => $user->getRoles(), ]); } diff --git a/security/login_link.rst b/security/login_link.rst index 8abe8a05a27..ed8bb195e15 100644 --- a/security/login_link.rst +++ b/security/login_link.rst @@ -401,7 +401,7 @@ The signed URL contains 3 parameters: The UNIX timestamp when the link expires. ``user`` - The value returned from ``$user->getUsername()`` for this user. + The value returned from ``$user->getUserIdentifier()`` for this user. ``hash`` A hash of ``expires``, ``user`` and any configured signature diff --git a/security/user_provider.rst b/security/user_provider.rst index d4c26e9cc5a..e7a3cdec79a 100644 --- a/security/user_provider.rst +++ b/security/user_provider.rst @@ -124,7 +124,7 @@ the ``property`` config key. If you want a bit more control over this - e.g. you want to find a user by ``email`` *or* ``username``, you can do that by making your ``UserRepository`` implement the :class:`Symfony\\Bridge\\Doctrine\\Security\\User\\UserLoaderInterface`. This -interface only requires one method: ``loadUserByUsername($username)``:: +interface only requires one method: ``loadUserByIdentifier($identifier)``:: // src/Repository/UserRepository.php namespace App\Repository; @@ -137,7 +137,9 @@ interface only requires one method: ``loadUserByUsername($username)``:: { // ... - public function loadUserByUsername(string $usernameOrEmail): ?User + // The loadUserByIdentifier() method was introduced in Symfony 5.3. + // In previous versions it was called loadUserByUsername() + public function loadUserByIdentifier(string $usernameOrEmail): ?User { $entityManager = $this->getEntityManager(); @@ -209,7 +211,7 @@ To finish this, remove the ``property`` key from the user provider in This tells Symfony to *not* query automatically for the User. Instead, when needed (e.g. because :doc:`user impersonation `, :doc:`Remember Me `, or some other security feature is -activated), the ``loadUserByUsername()`` method on ``UserRepository`` will be called. +activated), the ``loadUserByIdentifier()`` method on ``UserRepository`` will be called. .. _security-memory-user-provider: @@ -367,7 +369,7 @@ command will generate a nice skeleton to get you started:: namespace App\Security; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; - use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; + use Symfony\Component\Security\Core\Exception\UserNotFoundException; use Symfony\Component\Security\Core\User\PasswordUpgraderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; @@ -375,23 +377,21 @@ command will generate a nice skeleton to get you started:: class UserProvider implements UserProviderInterface, PasswordUpgraderInterface { /** - * Symfony calls this method if you use features like switch_user - * or remember_me. - * - * If you're not using these features, you do not need to implement - * this method. + * The loadUserByIdentifier() method was introduced in Symfony 5.3. + * In previous versions it was called loadUserByUsername() * - * @return UserInterface + * Symfony calls this method if you use features like switch_user + * or remember_me. If you're not using these features, you do not + * need to implement this method. * - * @throws UsernameNotFoundException if the user is not found + * @throws UserNotFoundException if the user is not found */ - public function loadUserByUsername(string $username) + public function loadUserByIdentifier(string $identifier): UserInterface { - // Load a User object from your data source or throw UsernameNotFoundException. - // The $username argument may not actually be a username: - // it is whatever value is being returned by the getUsername() - // method in your User class. - throw new \Exception('TODO: fill in loadUserByUsername() inside '.__FILE__); + // Load a User object from your data source or throw UserNotFoundException. + // The $identifier argument is whatever value is being returned by the + // getUserIdentifier() method in your User class. + throw new \Exception('TODO: fill in loadUserByIdentifier() inside '.__FILE__); } /** @@ -414,7 +414,7 @@ command will generate a nice skeleton to get you started:: } // Return a User object after making sure its data is "fresh". - // Or throw a UsernameNotFoundException if the user no longer exists. + // Or throw a UserNotFoundException if the user no longer exists. throw new \Exception('TODO: fill in refreshUser() inside '.__FILE__); } @@ -467,8 +467,8 @@ request, it's deserialized and then passed to your user provider to "refresh" it Then, the two User objects (the original from the session and the refreshed User object) are "compared" to see if they are "equal". By default, the core ``AbstractToken`` class compares the return values of the ``getPassword()``, -``getSalt()`` and ``getUsername()`` methods. If any of these are different, your -user will be logged out. This is a security measure to make sure that malicious +``getSalt()`` and ``getUserIdentifier()`` methods. If any of these are different, +your user will be logged out. This is a security measure to make sure that malicious users can be de-authenticated if core user data changes. However, in some cases, this process can cause unexpected authentication problems.