@@ -209,13 +209,20 @@ requires a user and some sort of "credentials" (e.g. a password).
209
209
Use the
210
210
:class: `Symfony\\ Component\\ Security\\ Http\\ Authenticator\\ Passport\\ Badge\\ UserBadge `
211
211
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)::
214
213
215
214
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
216
215
217
216
// ...
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.
219
226
220
227
.. note ::
221
228
@@ -255,6 +262,91 @@ using :ref:`the user provider <security-user-providers>`::
255
262
}
256
263
}
257
264
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
+ .. versionadded :: 7.3
275
+
276
+ The support of the user identifier normalizer was introduced in Symfony 7.3.
277
+
278
+ For instance, the example below uses a normalizer that converts usernames to a normalized, ASCII-only, lowercase format,
279
+ suitable for consistent comparison and storage.
280
+
281
+ // src/Security/NormalizedUserBadge.php
282
+ namespace App\S ecurity;
283
+
284
+ use Symfony\C omponent\S ecurity\H ttp\A uthenticator\P assport\B adge\U serBadge;
285
+ use Symfony\C omponent\S tring\U nicodeString;
286
+ use function Symfony\C omponent\S tring\u ;
287
+
288
+ final class NormalizedUserBadge extends UserBadge
289
+ {
290
+ public function __construct(string $identifier)
291
+ {
292
+ $callback = static fn (string $identifier) => u($identifier)->normalize(UnicodeString::NFKC)->ascii()->lower()->toString();
293
+
294
+ parent::__construct($identifier, null, $callback);
295
+ }
296
+ }
297
+
298
+ // src/Security/PasswordAuthenticator.php
299
+ namespace App\S ecurity;
300
+
301
+ final class PasswordAuthenticator extends AbstractLoginFormAuthenticator
302
+ {
303
+ // Simplified for brievety
304
+ public function authenticate(Request $request): Passport
305
+ {
306
+ $username = (string) $request->request->get('username', '');
307
+ $password = (string) $request->request->get('password', '');
308
+
309
+ $request->getSession()
310
+ ->set(SecurityRequestAttributes::LAST_USERNAME, $username);
311
+
312
+ return new Passport(
313
+ new NormalizedUserBadge($username),
314
+ new PasswordCredentials($password),
315
+ [
316
+ //All other useful badges
317
+ ]
318
+ );
319
+ }
320
+ }
321
+
322
+ .. note ::
323
+
324
+ Similarly, Google normalizes email addresses so that "john.doe", "j.hon.d.oe",
325
+ and "johndoe" all correspond to the same account.
326
+ This involves removing dots and converting the email address to lowercase
327
+ (though normalization specifics depend on your use case).
328
+
329
+ .. note ::
330
+
331
+ In enterprise applications, a user may need to use their identifier in multiple formats,
332
+ such as:
333
+ - ``john.doe@acme.com ``
334
+ - ``acme.com\jdoe ``
335
+ - ``https://acme.com/+jdoe ``
336
+ - ``acct:jdoe@acme.com ``
337
+
338
+ Normalizing these identifiers (e.g., converting to lowercase, trimming spaces,
339
+ or unifying formats) simplifies searches and ensures that the same user identity
340
+ is consistently recognized.
341
+ This is particularly useful to avoid duplicates caused by format variations.
342
+
343
+ User Credential
344
+ ~~~~~~~~~~~~~~~
345
+
346
+ The user credential is used to authenticate the user i.e. to verify
347
+ the validity of the provided information (such as a password, an API token,
348
+ or other custom credentials).
349
+
258
350
The following credential classes are supported by default:
259
351
260
352
:class: `Symfony\\ Component\\ Security\\ Http\\ Authenticator\\ Passport\\ Credentials\\ PasswordCredentials `
0 commit comments