I'm trying to implement FOSUserBundle with guard on Symfony 4.1. This is my authenticator :
<?php
namespace App\Security;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
private $em;
private $router;
private $passwordEncoder;
private $csrfTokenManager;
public function __construct(EntityManagerInterface $em, RouterInterface $router, UserPasswordEncoderInterface $passwordEncoder, CsrfTokenManagerInterface $csrfTokenManager)
{
$this->em = $em;
$this->router = $router;
$this->passwordEncoder = $passwordEncoder;
$this->csrfTokenManager = $csrfTokenManager;
}
public function getCredentials(Request $request)
{
$username = $request->request->get('_username');
$password = $request->request->get('_password');
$csrfToken = $request->request->get('_csrf_token');
if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken('authenticate', $csrfToken))) {
throw new InvalidCsrfTokenException('Invalid CSRF token.');
}
$request->getSession()->set(
Security::LAST_USERNAME,
$username
);
return [
'username' => $username,
'password' => $password,
];
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$username = $credentials['username'];
return $this->em->getRepository('App:User')
->findOneBy(['email' => $username]);
}
public function checkCredentials($credentials, UserInterface $user)
{
$password = $credentials['password'];
if ($this->passwordEncoder->isPasswordValid($user, $password)) {
return true;
}
return false;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
$targetPath = null;
// if the user hit a secure page and start() was called, this was
// the URL they were on, and probably where you want to redirect to
$targetPath = $this->getTargetPath($request->getSession(), $providerKey);
if (!$targetPath) {
$targetPath = $this->router->generate('homepage');
}
return new RedirectResponse($targetPath);
}
protected function getLoginUrl()
{
return $this->router->generate('fos_user_security_login');
}
/**
* Does the authenticator support the given Request?
*
* If this returns false, the authenticator will be skipped.
*
* @param Request $request
*
* @return bool
*/
public function supports(Request $request)
{
if($request->attributes->get('_route') !== 'fos_user_security_login'){
return false;
}
}
}
this is my security.yaml file :
security:
encoders:
App\Entity\User: bcrypt
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
logout: ~
guard:
authenticators:
- App\Security\LoginFormAuthenticator
# form_login:
# csrf_token_generator: security.csrf.token_manager
remember_me:
secret: '%env(APP_SECRET)%'
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
And the fos_user.yaml :
fos_user:
db_driver: 'orm'
user_class: App\Entity\User
firewall_name: main
service:
mailer: fos_user.mailer.twig_swift
from_email:
address: "[email protected]"
sender_name: "test"
registration:
form:
type: App\Form\UserRegistrationFormType
Whenever I go to login I get the following error :
You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.
I have the security-bundle installed and tried going through the steps provided in the official documentation : https://symfony.com/doc/current/security/guard_authentication.html
And I followed the tutorial on KnpUniversity but that was for Symfony 3 and it seems things do not work the same way anymore.
There must be something really obvious I'm not seeing.
Any advice would be very much appreciated.
Version info : - Symfony ^4.1 - FOSUserBundle ^2.1 - security-guard ^4.1
form_login
-- see (symfony.com/doc/current/security/form_login_setup.html) as an example – Alex.Barylski