@@ -491,6 +491,103 @@ egg to return a custom message if someone tries this:
491
491
curl -H " X-AUTH-TOKEN: ILuvAPIs" http://localhost:8000/
492
492
# {"message":"ILuvAPIs is not a real API key: it's just a silly phrase"}
493
493
494
+ Avoid Authenticating the Browser on Every Request
495
+ -------------------------------------------------
496
+
497
+ If you create a Guard login system that's used by a browser and you're experiencing
498
+ problems with your session or CSRF tokens, the cause could be bad behavior by your
499
+ authenticator. When a Guard authenticator is meant to be used by a browser, you
500
+ should *not * authenticate the user on *every * request. In other words, you need to
501
+ make sure the ``getCredentials() `` method *only * returns a non-null value when
502
+ you actually *need * to authenticate the user. Why? Because, when ``getCredentials() ``
503
+ returns a non-null value, for security purposes, the user's session is "migrated"
504
+ to a new session id.
505
+
506
+ This is an edge-case, and unless you're having session or CSRF token issues, you
507
+ can ignore this. Here is an example of good and bad behavior::
508
+
509
+ public function getCredentials(Request $request)
510
+ {
511
+ // GOOD behavior: only authenticate on a specific route
512
+ if ($request->attributes->get('_route') !== 'login_route' || !$request->isMethod('POST')) {
513
+ return null;
514
+ }
515
+
516
+ // e.g. your login system authenticates by the user's IP address
517
+ // BAD behavior: authentication will now execute on every request
518
+ // even if the user is already authenticated (due to the session)
519
+ return array('ip' => $request->getClientIp());
520
+ }
521
+
522
+ The problem occurs when your browser-based authenticator tries to authenticate
523
+ the user on *every * request - like in the IP address-based example above. There
524
+ are two possible fixes:
525
+
526
+ 1) If you do *not * need authentication to be stored in the session, set ``stateless: true ``
527
+ under your firewall.
528
+
529
+ 2) Update your authenticator to avoid authentication if the user is already authenticated:
530
+
531
+ .. code-block :: diff
532
+
533
+ // src/Security/MyIpAuthenticator.php
534
+ // ...
535
+
536
+ + use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
537
+
538
+ class MyIpAuthenticator
539
+ {
540
+ + private $tokenStorage;
541
+
542
+ + public function __construct(TokenStorageInterface $tokenStorage)
543
+ + {
544
+ + $this->tokenStorage = $tokenStorage;
545
+ + }
546
+
547
+ public function getCredentials(Request $request)
548
+ {
549
+ + // if there is already an authenticated user (likely due to the session)
550
+ + // then return null and skip authentication: there is no need.
551
+ + $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
552
+ + if (is_object($user)) {
553
+ + return null;
554
+ + }
555
+
556
+ return array('ip' => $request->getClientIp());
557
+ }
558
+ }
559
+
560
+ You'll also need to update your service configuration to pass the token storage:
561
+
562
+ .. configuration-block ::
563
+
564
+ .. code-block :: yaml
565
+
566
+ # app/config/services.yml
567
+ services :
568
+ app.token_authenticator :
569
+ class : AppBundle\Security\TokenAuthenticator
570
+ arguments : ['@security.token_storage']
571
+
572
+ .. code-block :: xml
573
+
574
+ <!-- app/config/services.xml -->
575
+ <services >
576
+ <service id =" app.token_authenticator" class =" AppBundle\Security\TokenAuthenticator" >
577
+ <argument type =" service" id =" security.token_storage" />
578
+ </service >
579
+ </services >
580
+
581
+ .. code-block :: php
582
+
583
+ // app/config/services.php
584
+ use AppBundle\Security\TokenAuthenticator;
585
+ use Symfony\Component\DependencyInjection\Definition;
586
+ use Symfony\Component\DependencyInjection\Reference;
587
+
588
+ $container->register('app.token_authenticator', TokenAuthenticator::class)
589
+ ->addArgument(new Reference('security.token_storage'));
590
+
494
591
Frequently Asked Questions
495
592
--------------------------
496
593
0 commit comments