Skip to content

Commit d2f062a

Browse files
committed
Avoiding authentication on every request with Guard
1 parent 35098ee commit d2f062a

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

security/guard_authentication.rst

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,103 @@ egg to return a custom message if someone tries this:
491491
curl -H "X-AUTH-TOKEN: ILuvAPIs" http://localhost:8000/
492492
# {"message":"ILuvAPIs is not a real API key: it's just a silly phrase"}
493493
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+
494591
Frequently Asked Questions
495592
--------------------------
496593

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy