Personnaliser la redirection après l'authentification en fonction de l'utilisateur

La configuration des firewall de Symfony permet de spécifier url de redirection en cas d'authentification réussit grâce à l'option default_target_path des form_login. Hélas vous ne pouvez pas personnaliser cette url en fonction de l'utilisateur, ce qui peux s'avérer utile si par exemple vous avez différent roles et que vous souhaitez rediriger votre utilisateur sur une page avec des accès restreint.

Authentication success handler

Pour cela, vous devez créer un authentication success handler personnaliser. Vous pouvez soit en créer un de tout pièce en prenant soins d'implémenter l'interface AuthenticationSuccessHandlerInterface, soit hériter du DefaultAuthenticationSuccessHandler et redéfinir la méthode determineTargetUrl.

<?php

namespace Acme\Bundle\AppBundle\Security;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
use Symfony\Component\Security\Http\HttpUtils;

class CustomAuthenticationSuccessHandler extends DefaultAuthenticationSuccessHandler
{
    private $authorizationChecker;

    public function __construct(HttpUtils $httpUtils, array $options = [], AuthorizationCheckerInterface $authorizationChecker = null)
    {
        $this->authorizationChecker = $authorizationChecker;
        parent::__construct($httpUtils, $options);
    }

    protected function determineTargetUrl(Request $request)
    {
        // Redirect to the wanted page
        if (null !== $this->providerKey && $targetUrl = $request->getSession()->get('_security.'.$this->providerKey.'.target_path')) {
            $request->getSession()->remove('_security.'.$this->providerKey.'.target_path');

            return $targetUrl;
        }

        // My redirection logic
        if ($this->authorizationChecker->isGranted('ROLE_FOOBAR') {
            return $this->httpUtils->generateUri($request, 'foobar');
        }

        // Default behavior
        return parent::determineTargetUrl($request);
    }
}

Ici par exemple, cet handler va rediriger les utilisateurs ayant le role ROLE_FOOBAR vers la route foobar. Pour les autres, le comportement par défaut s'appliquera.

Configuration

Déclarer votre service :

services:
    acme.security.custom_authentication_success_handler:
        class: Acme\Bundle\AppBundle\Security\CustomAuthenticationSuccessHandler
        arguments:
            - @security.http_utils
            - []
            - @?security.authorization_checker

Puis spécifier au form_login d'utiliser cet handler :

security:
    firewalls:
        secured_area:
            pattern:    ^/
            anonymous: ~
            form_login:
                success_handler: acme.security.custom_authentication_success_handler

Désormais, pour ce firewall, le nouveau handler sera utiliser. Pensez à le configurer sur vos autres firewall si besoin.

Les commentaires