symfony3 guard login form doesn't authenticate

1.4k Views Asked by At

I try to make a form login authentication with guard (symfony 3.2) but it doesn't work. The authentication is working, but when I'm redirected to the home page (accueil), I'm redirected to the login page without anthentication.
If I put in the controler of my home page

$user = $this->get('security.token_storage')->getToken();
dump($user); die;

I can see my user, the role but he is not authenticated.

DashboardController.php on line 23:
PostAuthenticationGuardToken {#133 ▼
 -providerKey: "main"
 -user: User {#457 ▶}
 -roles: array:1 [▼
   0 => Role {#120 ▼
     -role: "ROLE_SUPERADMIN"
   }
  ]    
-authenticated: false
-attributes: []
}

What I've missed ?

Security.ym

security:
encoders:
  EntBundle\Entity\User\User:
    algorithm: bcrypt

providers:
    database:
        entity:
          class: EntBundle:User\User
          property: username

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false

    main:
        pattern:    ^/
        anonymous: ~
        logout: ~
        guard:
          authenticators:
            - ent.login_authenticator

TestAuthenticator.php

namespace EntBundle\Security;

use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;

class TestAuthenticator extends AbstractGuardAuthenticator
{
private $em;
private $router;

public function __construct(EntityManager $em, RouterInterface $router)
{
    $this->em = $em;
    $this->router = $router;
}

public function getCredentials(Request $request)
{
    if ($request->getPathInfo() != '/login' || !$request->isMethod('POST'))     {
        return;
    }

    return [
        'username' => $request->request->get('_username'),
        'password' => $request->request->get('_password'),
    ];
}

public function getUser($credentials, UserProviderInterface $userProvider)
{
    $username = $credentials['username'];
    return $this->em->getRepository('EntBundle:User\User')->findOneBy(['username' => $username]);
}

public function checkCredentials($credentials, UserInterface $user)
{
  // this is just for test  
  return true;
}

public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
    $request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
    $url = $this->router->generate('login');
    return new RedirectResponse($url);
}

public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
    $url = $this->router->generate('accueil');
    return new RedirectResponse($url);
}

public function start(Request $request, AuthenticationException $authException = null)
{
    $url = $this->router->generate('login');
    return new RedirectResponse($url);
}

public function supportsRememberMe()
{
    return false;
}
}

DashboardController.php

namespace EntBundle\Controller\Dashboard;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;


class DashboardController extends Controller
{
/**
 * @Route("/accueil", name="accueil")
 */
public function indexAction()
{
    $user = $this->get('security.token_storage')->getToken();
    dump($user); die;
    return   $this->render('EntBundle:dashboard:dashboard_structure.html.twig');
}


/**
 * @Route("/login", name="login")
 */
public function loginAction()
{
    $authenticationUtils = $this->get('security.authentication_utils');
    $error = $authenticationUtils->getLastAuthenticationError();
    $lastUsername = $authenticationUtils->getLastUsername();

    return $this->render('EntBundle::login.html.twig', [
        'last_username' => $lastUsername,
        'error' => $error,
    ]);
}

/**
 * @Route("/logout", name="logout")
 */
public function logoutAction()
{
}
}

EDIT:
Thanks leo_ap for your help but the problem doesnt come from there.
The config session is like this :

session:
     handler_id:  session.handler.native_file
     save_path:   "%kernel.root_dir%/../var/sessions/%kernel.environment%"

and if I check in the save path folder I have session file created but not authenticated.

_sf2_attributes|a:1:{s:26:"_security.main.target_path";s:29:"http://localhost:8000/accueil";}_sf2_flashes|a:0:{}_sf2_meta|a:3:{s:1:"u";i:1488245179;s:1:"c";i:1488244922;s:1:"l";s:1:"0";}

If I try the normal login_form with security.yml it's working fine...
I've try with handler_id and save_path at null with no success.

EDIT2:
I've found why I'm always redirected to the login page, because I'm logged out!

[2017-02-28 09:16:34] security.INFO: The security token was removed due to an AccountStatusException. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationExpiredException(code: 0):  at /home/philippe/Documents/symfony/vendor/symfony/symfony/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php:86)"}

and in GuardAuthenticationProvider.php (86)

   The listener *only* passes PreAuthenticationGuardToken instances.
   This means that an authenticated token (e.g.PostAuthenticationGuardToken)
   is being passed here, which happens if that token becomes "not authenticated" (e.g. happens if the user changes between requests).  
  In this case, the user should be logged out, so we will return an AnonymousToken to accomplish that.

But Why ???

1

There are 1 best solutions below

1
On

May be your Session that isn't persisting the token. Check your Session configuration, inside: config.yml. in the framework option, there is session. See how the handler_id and save_path are configured. It may be that your php instalation is unable to handle the sessions on the configured path. Try to put null to handler_id and save_path to force php use its own build in configurations to handle sessions.

config.yml file:

framework:

    { .. Other configurations ..}

    session:
        handler_id:  null
        save_path:   null

    { .. More configurations ..}