Amaury Leroux de Lens Robin Chalas
Contributed by Amaury Leroux de Lens and Robin Chalas in #16835

The Guard component brings many layers of authentication together, making it much easier to create complex authentication systems where you have total control. In Symfony 3.4 we improved Guard a bit with some minor tweaks.

First, the Symfony\\Component\\Security\\Guard\\GuardAuthenticatorInterface is deprecated and will be removed in Symfony 4.0. Use Symfony\\Component\\Security\\Guard\\AuthenticatorInterface instead.

Second, the getCredentials() method no longer has two responsibilities. Before, if you returned null in this method, the authenticator class was skipped. Now, if you return null you'll see a \UnexpectedValueException.

The previous skipping logic of getCredentials() has been moved to a new method called supports() which returns a boolean value indicating if the authenticator should be used or not for this particular request. In summary:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// BEFORE
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;

class TokenAuthenticator extends AbstractGuardAuthenticator
{
    public function getCredentials(Request $request)
    {
        if (!$token = $request->headers->get('X-AUTH-TOKEN')) {
            return null;
        }

        return ['token' => $token];
    }
}

// AFTER
class TokenAuthenticator extends AbstractGuardAuthenticator
{
    public function supports(Request $request)
    {
        return $request->headers->has('X-AUTH-TOKEN');
    }

    public function getCredentials(Request $request)
    {
        return ['token' => $request->headers->get('X-AUTH-TOKEN')];
    }
}

This separation of concerns between supports() and getCredentials() will allow developers to create dedicated guard authenticators for each application need. For example, a common abstract class or a trait (e.g. ApiBaseAuthenticator.php) could be used to share the common stages of the authentication (getUser(), checkCredentials(), createAuthenticatedToken(), etc.) and some concrete final classes (ApiHeaderAuthenticator.php, ApiPayloadAuthenticator.php, etc.) will explicitly indicate the use-cases they manage (supports() and getCredentials()):

1
2
3
4
5
6
7
8
your-project/
└── src/
    └── Security/
        └── Authenticator
            ├── ApiBaseAuthenticator.php
            ├── ApiHeaderAuthenticator.php
            ├── ApiPayloadAuthenticator.php
            └── ApiQueryAuthenticator.php
Published in #Living on the edge