Skip to content

Commit 98f4fc4

Browse files
committed
Update custom authenticator docs to include identifier normalization
Improve the documentation for custom authenticators by detailing the concept of user identifier normalization. Introduced the `NormalizedUserBadge` example to demonstrate how to simplify and standardize identifiers. Clarified how normalization avoids duplicates and ensures consistent user recognition.
1 parent 0b180d5 commit 98f4fc4

File tree

1 file changed

+88
-3
lines changed

1 file changed

+88
-3
lines changed

security/custom_authenticator.rst

+88-3
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,20 @@ requires a user and some sort of "credentials" (e.g. a password).
209209
Use the
210210
:class:`Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\UserBadge`
211211
to attach the user to the passport. The ``UserBadge`` requires a user
212-
identifier (e.g. the username or email), which is used to load the user
213-
using :ref:`the user provider <security-user-providers>`::
212+
identifier (e.g. the username or email)::
214213

215214
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
216215

217216
// ...
218-
$passport = new Passport(new UserBadge($email), $credentials);
217+
$passport = new Passport(new UserBadge($userIdentifier), $credentials);
218+
219+
User Identifier
220+
~~~~~~~~~~~~~~~
221+
222+
The user identifier is a unique string that identifies the user. It is used
223+
to load the user using :ref:`the user provider <security-user-providers>`.
224+
This identifier is often something like the user's email address or username,
225+
but it could be any unique value associated with the user.
219226

220227
.. note::
221228

@@ -255,6 +262,84 @@ using :ref:`the user provider <security-user-providers>`::
255262
}
256263
}
257264

265+
It is a good practice to normalize the user identifier before using it.
266+
For example, this ensures that variations such as "john.doe", "John.Doe",
267+
or "JOHN.DOE" refer to the same user.
268+
Normalization can include converting the identifier to lowercase
269+
and trimming unnecessary spaces.
270+
You can optionally pass a user identifier normalizer as third argument to the
271+
``UserBadge``. This callable receives the ``$userIdentifier``
272+
and must return a normalized user identifier as a string.
273+
274+
// src/Security/NormalizedUserBadge.php
275+
namespace App\Security;
276+
277+
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
278+
use Symfony\Component\String\UnicodeString;
279+
use function Symfony\Component\String\u;
280+
281+
final class NormalizedUserBadge extends UserBadge
282+
{
283+
public function __construct(string $identifier)
284+
{
285+
$callback = static fn (string $identifier) => u($identifier)->normalize(UnicodeString::NFKC)->ascii()->lower()->toString();
286+
287+
parent::__construct($identifier, null, $callback);
288+
}
289+
}
290+
291+
// src/Security/PasswordAuthenticator.php
292+
namespace App\Security;
293+
294+
final class PasswordAuthenticator extends AbstractLoginFormAuthenticator
295+
{
296+
// Simplified for brievety
297+
public function authenticate(Request $request): Passport
298+
{
299+
$username = (string) $request->request->get('username', '');
300+
$password = (string) $request->request->get('password', '');
301+
302+
$request->getSession()
303+
->set(SecurityRequestAttributes::LAST_USERNAME, $username);
304+
305+
return new Passport(
306+
new NormalizedUserBadge($username),
307+
new PasswordCredentials($password),
308+
[
309+
//All other useful badges
310+
]
311+
);
312+
}
313+
}
314+
315+
.. note::
316+
317+
Similarly, Google normalizes email addresses so that "john.doe", "j.hon.d.oe",
318+
and "johndoe" all correspond to the same account.
319+
This involves removing dots and converting the email address to lowercase
320+
(though normalization specifics depend on your use case).
321+
322+
.. note::
323+
324+
In enterprise applications, a user may need to use their identifier in multiple formats,
325+
such as:
326+
327+
- ``acme.com\jdoe``
328+
- ``https://acme.com/+jdoe``
329+
- ``acct:[email protected]``
330+
331+
Normalizing these identifiers (e.g., converting to lowercase, trimming spaces,
332+
or unifying formats) simplifies searches and ensures that the same user identity
333+
is consistently recognized.
334+
This is particularly useful to avoid duplicates caused by format variations.
335+
336+
User Credential
337+
~~~~~~~~~~~~~~~
338+
339+
The user credential is used to authenticate the user i.e. to verify
340+
the validity of the provided information (such as a password, an API token,
341+
or other custom credentials).
342+
258343
The following credential classes are supported by default:
259344

260345
:class:`Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\PasswordCredentials`

0 commit comments

Comments
 (0)