Ryan Weaver
Contributed by Ryan Weaver in #14673

The Symfony Security component is divided into two main parts: authentication and authorization. The authorization subsystem checks whether the user has permission to access the given resource. This system is related to roles and voters and is both powerful and simple to use.

The authentication subsystem checks the user identity through any of the supported methods: username + password, certificates, API tokens, etc. This subsystem is powerful and flexible, but lots of Symfony developers struggle with its complexity.

A new security-related component called Guard aims at simplifying the authentication subsystem. This radical new approach is based on creating just one PHP class that implements GuardAuthenticatorInterface. This interface defines the following seven methods:

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
interface GuardAuthenticatorInterface
{
    /**
     * Get the authentication credentials from the request. If you return null,
     * authentication will be skipped.
     *
     * For example, for a form login, you might:
     *
     *      return array(
     *          'username' => $request->request->get('_username'),
     *          'password' => $request->request->get('_password'),
     *      );
     *
     * Or for an API token that's on a header, you might use:
     *
     *      return array('api_key' => $request->headers->get('X-API-TOKEN'));
     */
    public function getCredentials(Request $request);

    /**
     * Return a UserInterface object based on the credentials returned by getCredentials()
     */
    public function getUser($credentials, UserProviderInterface $userProvider);

    /**
     * Throw an AuthenticationException if the credentials returned by
     * getCredentials() are invalid.
     */
    public function checkCredentials($credentials, UserInterface $user);

    /**
     * Create an authenticated token for the given user. You can skip this
     * method by extending the AbstractGuardAuthenticator class from your
     * authenticator.
     */
    public function createAuthenticatedToken(UserInterface $user, $providerKey);

    /**
     * Called when authentication executed, but failed (e.g. wrong username password).
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception);

    /**
     * Called when authentication executed and was successful (for example a
     * RedirectResponse to the last page they visited)
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey);

    /**
     * Does this method support remember me cookies?
     */
    public function supportsRememberMe();
}

After implementing this interface you'll be able to authenticate users via login forms, Facebook, Twitter or any other OAuth-based service, API tokens, etc. Moreover, you'll be able to customize successful and failure behavior very easily.

Showing a complete example of the Guard component in action is beyond the purpose of this article, but you can read (and help us finish) the work in progress documentation of the component and its official tutorial.

Published in #Living on the edge