Symfony & Guard: "The security token was removed due to an AccountStatusException" - php

I tried to create an authenticator for my login form, but I always am unlogged for some unclear reason.
[2016-10-05 18:54:53] security.INFO: Guard authentication successful! {"token":"[object] (Symfony\\Component\\Security\\Guard\\Token\\PostAuthenticationGuardToken: PostAuthenticationGuardToken(user=\"test#test.test\", authenticated=true, roles=\"ROLE_USER\"))","authenticator":"AppBundle\\Security\\Authenticator\\FormLoginAuthenticator"} []
[2016-10-05 18:54:54] security.INFO: An AuthenticationException was thrown; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationExpiredException(code: 0): at /space/products/insurance/vendor/symfony/symfony/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php:86)"} []
[2016-10-05 18:54:54] security.INFO: The security token was removed due to an AccountStatusException. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationExpiredException(code: 0): at /space/products/insurance/vendor/symfony/symfony/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php:86)"} []
I don't understand this "AuthenticationExpiredException" as I have nothing stateless, nor any expiration in any way nowhere in my app.
Does this issue speak to anyone?
Edit 1
After a bunch of hours, it looks like I am unlogged because of the {{ is_granted('ROLE_USER') }} in Twig. Don't see why anyway.
Edit 2
If I dump() my security token on the onAuthenticationSuccess authenticator's method, authenticated = true.
But, If I dump() my security token after a redirect or when accessing a new page, 'authenticated' = false.
Why the hell my authentication isn't stored.
app/config/security.yml
security:
encoders:
AppBundle\Security\User\Member:
algorithm: bcrypt
cost: 12
providers:
members:
id: app.provider.member
role_hierarchy:
ROLE_ADMIN: "ROLE_USER"
firewalls:
dev:
pattern: "^/(_(profiler|wdt|error)|css|images|js)/"
security: false
main:
pattern: "^/"
anonymous: ~
logout: ~
guard:
authenticators:
- app.authenticator.form_login
access_control:
- { path: "^/connect", role: "IS_AUTHENTICATED_ANONYMOUSLY" }
- { path: "^/register", role: "IS_AUTHENTICATED_ANONYMOUSLY" }
- { path: "^/admin", role: "ROLE_ADMIN" }
- { path: "^/user", role: "ROLE_USER" }
- { path: "^/logout", role: "ROLE_USER" }
AppBundle/Controller/SecurityController.php
<?php
namespace AppBundle\Controller;
use AppBundle\Base\BaseController;
use AppBundle\Form\Type\ConnectType;
use AppBundle\Security\User\Member;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
class SecurityController extends BaseController
{
/**
* #Route("/connect", name="security_connect")
* #Template()
*/
public function connectAction(Request $request)
{
$connectForm = $this
->createForm(ConnectType::class)
->handleRequest($request)
;
return [
'connect' => $connectForm->createView(),
];
}
}
AppBundle/Form/Type/ConnectType.php
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\Validator\Constraints;
use EWZ\Bundle\RecaptchaBundle\Form\Type\EWZRecaptchaType;
use EWZ\Bundle\RecaptchaBundle\Validator\Constraints\IsTrue as RecaptchaTrue;
class ConnectType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', Type\EmailType::class, [
'label' => 'Your email',
'required' => true,
'constraints' => [
new Constraints\Length(['min' => 8])
],
])
->add('password', Type\PasswordType::class, [
'label' => 'Your password',
'constraints' => new Constraints\Length(['min' => 8, 'max' => 4096]), /* CVE-2013-5750 */
])
->add('recaptcha', EWZRecaptchaType::class, [
'label' => 'Please tick the checkbox below',
'constraints' => [
new RecaptchaTrue()
],
])
->add('submit', Type\SubmitType::class, [
'label' => 'Connect',
])
;
}
}
AppBundle/Security/Authenticator/FormLoginAuthenticator.php
<?php
namespace AppBundle\Security\Authenticator;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use AppBundle\Form\Type\ConnectType;
class FormLoginAuthenticator extends AbstractFormLoginAuthenticator
{
private $container; // ¯\_(ツ)_/¯
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function getCredentials(Request $request)
{
if ($request->getPathInfo() !== '/connect') {
return null;
}
$connectForm = $this
->container
->get('form.factory')
->create(ConnectType::class)
->handleRequest($request)
;
if ($connectForm->isValid()) {
$data = $connectForm->getData();
return [
'username' => $data['email'],
'password' => $data['password'],
];
}
return null;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
return $userProvider->loadUserByUsername($credentials['username']);
}
public function checkCredentials($credentials, UserInterface $user)
{
$isValid = $this
->container
->get('security.password_encoder')
->isPasswordValid($user, $credentials['password'])
;
if (!$isValid) {
throw new BadCredentialsException();
}
return true;
}
protected function getLoginUrl()
{
return $this
->container
->get('router')
->generate('security_connect')
;
}
protected function getDefaultSuccessRedirectUrl()
{
return $this
->container
->get('router')
->generate('home')
;
}
}
AppBundle/Security/Provider/MemberProvider.php
<?php
namespace AppBundle\Security\Provider;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use AppBundle\Security\User\Member;
use Api\Gateway\RequestResponse\RequestResponseHandlerInterface;
use Api\Business\InsuranceWebsite\Action\GetInsuranceMember\GetInsuranceMemberRequest;
use Api\Gateway\Exception\NoResultException;
class MemberProvider implements UserProviderInterface
{
protected $gateway;
public function __construct(RequestResponseHandlerInterface $gateway)
{
$this->gateway = $gateway;
}
public function loadUserByUsername($username)
{
try {
$response = $this->gateway->handle(
new GetInsuranceMemberRequest($username)
);
} catch (NoResultException $ex) {
throw new UsernameNotFoundException(
sprintf('Username "%s" does not exist.', $username)
);
}
$member = new Member();
$member->setId($response->getId());
$member->setUsername($response->getEmail());
$member->setPassword($response->getPassword());
$member->setCompanyId($response->getCompanyId());
$member->setFirstname($response->getFirstname());
$member->setLastname($response->getLastname());
$member->setIsManager($response->isManager());
$member->setIsEnabled($response->isEnabled());
return $member;
}
public function refreshUser(UserInterface $user)
{
if (!$user instanceof Member) {
throw new UnsupportedUserException(
sprintf('Instances of "%s" are not supported.', get_class($user))
);
}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $class === Member::class;
}
}
AppBundle/Security/User/Member.php
<?php
namespace AppBundle\Security\User;
use Symfony\Component\Security\Core\User\UserInterface;
class Member implements UserInterface
{
private $id;
private $username;
private $password;
private $companyId;
private $firstname;
private $lastname;
private $isManager;
private $isEnabled;
private $roles = ['ROLE_USER'];
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
return $this;
}
public function getUsername()
{
return $this->username;
}
public function setUsername($username)
{
$this->username = $username;
return $this;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function getCompanyId()
{
return $this->companyId;
}
public function setCompanyId($companyId)
{
$this->companyId = $companyId;
return $this;
}
public function getFirstname()
{
return $this->firstname;
}
public function setFirstname($firstname)
{
$this->firstname = $firstname;
return $this;
}
public function getLastname()
{
return $this->lastname;
}
public function setLastname($lastname)
{
$this->lastname = $lastname;
return $this;
}
public function isManager()
{
return $this->isManager;
}
public function setIsManager($isManager)
{
$this->isManager = $isManager;
return $this;
}
public function IsEnabled()
{
return $this->isEnabled;
}
public function setIsEnabled($isEnabled)
{
$this->isEnabled = $isEnabled;
return $this;
}
public function eraseCredentials()
{
$this->password = null;
}
public function hasRole($role)
{
return in_array($role, $this->roles);
}
public function getRoles()
{
return $this->roles;
}
public function addRole($role)
{
if (!$this->hasRole($role)) {
$this->roles[] = $role;
}
return $this;
}
public function removeRole($role)
{
$index = array_search($role, $this->roles);
if ($index !== false) {
unset($this->roles[$index]);
$this->roles = array_values($this->roles);
}
return $this;
}
public function getSalt()
{
return null;
}
}
src/AppBundle/Resources/config/services.yml
imports:
parameters:
app.provider.member.class: AppBundle\Security\Provider\MemberProvider
app.authenticator.form_login.class: AppBundle\Security\Authenticator\FormLoginAuthenticator
services:
app.provider.member:
class: %app.provider.member.class%
arguments: ['#gateway']
app.authenticator.form_login:
class: %app.authenticator.form_login.class%
arguments: ["#service_container"]

I found my bug, after 8 hours of hard work. I promise, I'll drink a bulk of beers after this comment!
I located my issue in the Symfony\Component\Security\Core\Authentication\Token\AbstractToken::hasUserChanged() method, which compares user stored in the session, and the one returned by the refreshUser of your provider.
My user entity was considered changed because of this condition:
if ($this->user->getPassword() !== $user->getPassword()) {
return true;
}
In fact, before being stored in the session, the eraseCredentials() method is called on your user entity so the password is removed. But the password exists in the user the provider returns.
That's why in documentations, they show plainPassword and password properties... They keep password in the session, and eraseCredentials just cleans up `plainPassword. Kind of tricky.
Se we have 2 solutions:
having eraseCredentials not touching password, can be useful if you want to unauthent your member when he changes his password somehow.
implementing EquatableInterface in our user entity, because the following test is called before the one above.
if ($this->user instanceof EquatableInterface) {
return !(bool) $this->user->isEqualTo($user);
}
I decided to implement EquatableInterface in my user entity, and I'll never forget to do it in the future.
<?php
namespace AppBundle\Security\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\EquatableInterface;
class Member implements UserInterface, EquatableInterface
{
// (...)
public function isEqualTo(UserInterface $user)
{
return $user->getId() === $this->getId();
}
}

Related

Upgrade to new symfony authenticator system: can't log in anymore [duplicate]

This question already has an answer here:
Symfony simple Login form with the new authentication method not working
(1 answer)
Closed 1 year ago.
Following an upgrade from Symfony 4 to the latest Symfony 5 version, I've tried upgrading my registration and login form guard thingies to become authenticator thingies.
After trying a lot of stuff, and using the make:user and make:auth commands again and again, I'm now in a situation where I have no warning, no error, just when I try to log in, nothing happens: it doesn't matter whether the username/password combination is correct or not, I just get back to the login form.
Here are the files I believe could be relevant to the issue:
config/packages/security.yaml
security:
enable_authenticator_manager: true
password_hashers:
App\Entity\Player:
algorithm: auto
providers:
app_user_provider:
entity:
class: App\Entity\Player
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: app_user_provider
custom_authenticator: App\Security\LoginFormAuthenticator
logout:
path: app_logout
remember_me:
secret: '%kernel.secret%'
lifetime: 604800
path: /
always_remember_me: true
switch_user: true
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
src/Controller/SecurityController.php
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class SecurityController extends AbstractController
{
/**
* #Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
// If the user is logged in, redirect them to their profile page.
if ($this->getUser()) {
return $this->redirectToRoute('player_control_panel');
}
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]);
}
/**
* #Route("/logout", name="app_logout")
*/
public function logout()
{
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
}
}
src/Entity/Player.php
<?php
namespace App\Entity;
use App\Repository\PlayerRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* #ORM\Entity(repositoryClass=PlayerRepository::class)
* #UniqueEntity(fields={"email"}, message="There is already an account with this email")
*/
class Player implements UserInterface, PasswordAuthenticatedUserInterface
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=180, unique=true)
*/
private $email;
/**
* #ORM\Column(type="json")
*/
private $roles = [];
/**
* #var string The hashed password
* #ORM\Column(type="string")
*/
private $password;
/**
* #ORM\Column(type="boolean")
*/
private $isVerified = false;
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->email;
}
/**
* #deprecated since Symfony 5.3, use getUserIdentifier instead
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* #see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* #see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* Returning a salt is only needed, if you are not using a modern
* hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
*
* #see UserInterface
*/
public function getSalt(): ?string
{
return null;
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function isVerified(): bool
{
return $this->isVerified;
}
public function setIsVerified(bool $isVerified): self
{
$this->isVerified = $isVerified;
return $this;
}
}
src/Security/LoginFormAuthenticator.php
<?php
namespace App\Security;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
{
use TargetPathTrait;
public const LOGIN_ROUTE = 'app_login';
private UrlGeneratorInterface $urlGenerator;
public function __construct(UrlGeneratorInterface $urlGenerator)
{
$this->urlGenerator = $urlGenerator;
}
public function authenticate(Request $request): PassportInterface
{
$email = $request->request->get('email', '');
$request->getSession()->set(Security::LAST_USERNAME, $email);
return new Passport(
new UserBadge($email),
new PasswordCredentials($request->request->get('password', '')),
[
new CsrfTokenBadge('authenticate', $request->request->get('_csrf_token')),
]
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
$request->getSession()->getFlashBag()->add('success', "You are now signed in. Greetings, commander.");
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
return new RedirectResponse($targetPath);
}
return new RedirectResponse($this->urlGenerator->generate('app_index'));
}
protected function getLoginUrl(Request $request): string
{
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
}
}
I just can't see what's going wrong, if you have an idea, or even if you can just give me an idea of how I could get an idea of what's going wrong, I'd appreciate it. Thank you!
Sorry, that's a duplicate of Symfony simple Login form with the new authentication method not working which I found a few minutes after posting this (I swear I searched before and didn't find it).
The issue is indeed the supports() method missing in the authenticator class, the one in the abstract login form authenticator apparently isn't sufficient. Adding that method fixed it:
in src/Security/LoginFormAuthenticator.php
public function supports(Request $request): bool
{
return self::LOGIN_ROUTE === $request->attributes->get('_route')
&& $request->isMethod('POST');
}
Full file:
<?php
namespace App\Security;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
{
use TargetPathTrait;
public const LOGIN_ROUTE = 'app_login';
private UrlGeneratorInterface $urlGenerator;
public function __construct(UrlGeneratorInterface $urlGenerator)
{
$this->urlGenerator = $urlGenerator;
}
public function supports(Request $request): bool
{
return self::LOGIN_ROUTE === $request->attributes->get('_route')
&& $request->isMethod('POST');
}
public function authenticate(Request $request): PassportInterface
{
$email = $request->request->get('email', '');
$request->getSession()->set(Security::LAST_USERNAME, $email);
return new Passport(
new UserBadge($email),
new PasswordCredentials($request->request->get('password', '')),
[
new CsrfTokenBadge('authenticate', $request->request->get('_csrf_token')),
]
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
$request->getSession()->getFlashBag()->add('success', "You are now signed in. Greetings, commander.");
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
return new RedirectResponse($targetPath);
}
return new RedirectResponse($this->urlGenerator->generate('app_index'));
}
protected function getLoginUrl(Request $request): string
{
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
}
}

Symfony Authentication after register

I'm working on a mini web project and i'm building it in symfony, so after i created registeration and login form, i realised that after registration user won't be directly authenticated, so i made some research to see how it works but i'm facing some problems and i'm new to this framework.
Here's the controller code (the users class is called Players in my app because i'm developping an escape game)
<?php
namespace App\Controller;
use App\Entity\Items;
use App\Entity\Players;
use App\Entity\Inventaire;
use App\Security\TokenAuthenticator;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class PlayerController extends AbstractController
{
private $em;
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
/**
* #Route("/player", name="player")
*/
public function index(): Response
{
return $this->render('player/index.html.twig', [
'controller_name' => 'PlayerController',
]);
}
/**
* #Route("/login_Player", name="login_Player")
*/
public function loginPlayer(){
return $this->render("app/player_interface.html.twig");
}
/**
* #Route("/redirect_player", name="redirect_player")
*/
public function redirectPlayer(){
$player = $this->getUser();
if($player){
return $this->render("app/player_interface.html.twig",['player'=>$player]);
}
else{
return $this-render("app/home.html.twig");
}
}
/**
* #Route("/logout_Player", name="logout_Player")
*/
public function logoutPlayer(){
return $this->render("app/home.html.twig");
}
/**
* #Route("/create_interface", name="create_Player")
*/
public function createPlayer(Request $request,EntityManagerInterface $em,UserPasswordEncoderInterface $encoder,GuardAuthenticatorHandler $guardHandler,TokenAuthenticator $authenticator): Response
{
$repository = $this->getDoctrine()->getRepository(Players::class);
if($request->request->count()>0){
if(($repository->findBy(["username"=>$request->request->get("pseudo")])) || ($repository->findBy(["email"=>$request->request->get("mail")]))){
return $this->render("app/home.html.twig",["msg"=>"Id ou mail déja utilisé!"]);
}
else{
$coord=[48.8413672,2.4223428];
$player = new Players();
$player->setUsername($request->request->get("pseudo"))
->setPassword($request->request->get("pass"))
->setEmail($request->request->get("mail"));
$player->setLongitude($coord[1]);
$player->setLatitude($coord[0]);
$inventaire=new Inventaire();
$inventaire->setPlayerId($player);
$player->setInventaire($inventaire);
$this->em=$em;
$hash=$encoder->encodePassword($player, $player->getPassword());
$player->setPassword($hash);
$em->persist($player);
$em->persist($inventaire);
$em->flush();
return $guardHandler->authenticateUserAndHandleSuccess($player,$request,$authenticator,'main');
//return $this->render("app/player_interface.html.twig",['player'=>$player]);//'inventaire'=>$inventaire]);
}
}
}
/**
* #Route("/add_item",name="add_item")
*/
public function addItem(Request $request,EntityManagerInterface $em){
if ($request->isXmlHttpRequest()){
$this->em=$em;
$player = $this->getUser();
$inventaire=$player->getInventaire();
$item=new Items();
$item->setDescription($request->request->get("description"))
->setVisibility($request->request->get("visibility"))
->setNiveau($request->request->get("icon_id"));
$inventaire->addItemId($item);
$em->flush();
return new JsonResponse(array("player"=>$player,"inventaire"=>$inventaire->getItem_id()));
}
else{
return $this->render("app/player_interface.html.twig");
}
}
/**
* #Route("/move_player",name="move_player")
*/
public function movePlayer(Request $request,EntityManagerInterface $em){
if ($request->isXmlHttpRequest()){
$this->em=$em;
$player = $this->getUser();
$player->setLongitude($request->request->get("longitude"))
->setLatitude($request->request->get("latitude"));
$em->flush();
return new JsonResponse(array("player"=>$player));
}
else{
return $this->render("app/player_interface.html.twig");
}
}
/**
* #Route("affiche_scenario", name="affiche_scenario")
*/
public function afficheScenario(Request $request){
if ($request->isXmlHttpRequest()){
$repository = $this->getDoctrine()->getRepository(Scenarios::class);
return new JsonResponse($repository->findBy($request->request->get("num_scenario")));
}
else{
return $this->render("app/player_interface.html.twig");
}
}
}
?>
and this is the tokenauthenticator class:
<?php
// src/Security/TokenAuthenticator.php
namespace App\Security;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class TokenAuthenticator extends AbstractGuardAuthenticator
{
private $em;
protected $router;
public function __construct(EntityManagerInterface $em,HttpUtils $httpUtils, $router)
{
$this->em = $em;
$this->router = $router;
}
/**
* Called on every request to decide if this authenticator should be
* used for the request. Returning `false` will cause this authenticator
* to be skipped.
*/
public function supports(Request $request)
{
return $request->headers->has('X-AUTH-TOKEN');
}
/**
* Called on every request. Return whatever credentials you want to
* be passed to getUser() as $credentials.
*/
public function getCredentials(Request $request)
{
return $request->headers->get('X-AUTH-TOKEN');
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
if (null === $credentials) {
// The token header was empty, authentication fails with HTTP Status
// Code 401 "Unauthorized"
return null;
}
// The "username" in this case is the apiToken, see the key `property`
// of `your_db_provider` in `security.yaml`.
// If this returns a user, checkCredentials() is called next:
return $userProvider->loadUserByUsername($credentials);
}
public function checkCredentials($credentials, UserInterface $user)
{
// Check credentials - e.g. make sure the password is valid.
// In case of an API token, no credential check is needed.
// Return `true` to cause authentication success
return true;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
/*if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}*/
return new RedirectResponse($this->router->generate('redirect_player'));
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$data = [
// you may want to customize or obfuscate the message first
'message' => strtr($exception->getMessageKey(), $exception->getMessageData())
// or to translate this message
// $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
];
return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
}
/**
* Called when authentication is needed, but it's not sent
*/
public function start(Request $request, AuthenticationException $authException = null)
{
$data = [
// you might translate this message
'message' => 'Authentication Required'
];
return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
}
public function supportsRememberMe()
{
return false;
}
}
?>
And finaly the security.yaml file
security:
encoders:
App\Entity\Players:
algorithm: bcrypt
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
users_in_memory: { memory: null }
in_database:
entity:
class: App\Entity\Players
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
lazy: true
#provider: users_in_memory
provider: in_database
form_login:
login_path: login_Player
check_path: login_Player
#failure_handler: App\Security\authentication_failure_handler
csrf_token_generator: security.csrf.token_manager
failure_path: home
guard:
authenticators:
- App\Security\TokenAuthenticator
logout:
path: logout_Player
target: home
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
The TokenAuthenticator class i found it on symfony and another tutorial so i don't really understand the mechanism and when i try to register a user now, the app shows me an error:
Cannot autowire service "App\Security\TokenAuthenticator": argument "$router" of method "__construct()" has no type-hint, you should configure its value explicitly.
Thanks in advance everyone and have a good day.
https://symfony.com/doc/current/service_container/autowiring.html
Autowiring allows you to manage services in the container with minimal configuration. It reads the type-hints on your constructor (or other methods) and automatically passes the correct services to each method. Symfony’s autowiring is designed to be predictable: if it is not absolutely clear which dependency should be passed, you’ll see an actionable exception.
You must type hint your arguments passed to the constructor so that symfony can pass them to you automatically thanks to autowiring:
// others uses
use Symfony\Component\Routing\RouterInterface;
class TokenAuthenticator extends AbstractGuardAuthenticator
{
private $em;
protected $router;
public function __construct(EntityManagerInterface $em, HttpUtils $httpUtils, RouterInterface $router)
{
$this->em = $em;
$this->router = $router;
}
Or if you want juste to generate urls, you cant use the UrlGeneratorInterface instead of the router:
// ...
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class TokenAuthenticator extends AbstractGuardAuthenticator
{
private $em;
protected $urlGenerator;
public function __construct(EntityManagerInterface $em, HttpUtils $httpUtils, UrlGeneratorInterface $urlGenerator)
{
$this->em = $em;
$this->urlGenerator = $urlGenerator;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
return new RedirectResponse($this->urlGenerator->generate('redirect_player'));
}

Symfony User lost after onAuthenticationSuccess redirect

Have followed the instructions on: https://symfony.com/doc/current/security/form_login_setup.html, and in step 3 (in the onAuthenticationSuccess method) - if I leave the Exception in, the profiler bar shows the user logged in, however if I comment in the redirect, the user is lost on the following page. Sessions are set up and working as pdo.
Anyone have any ideas?
LoginFormAuthenticator.php
<?php
namespace App\Security;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
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 $entityManager;
private $urlGenerator;
private $csrfTokenManager;
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
}
public function supports(Request $request)
{
return 'app_login' === $request->attributes->get('_route')
&& $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'email' => $request->request->get('email'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['email']
);
return $credentials;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
$user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $credentials['email']]);
if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Email could not be found.');
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
// Check the user's password or other credentials and return true or false
// If there are no credentials to check, you can just return true
return true;
//throw new \Exception('TODO: check the credentials inside '.__FILE__);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
//throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
return new RedirectResponse($this->urlGenerator->generate('app_dashboard'));
}
protected function getLoginUrl()
{
return $this->urlGenerator->generate('app_login');
}
}
DashboardController.php
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class DashboardController extends AbstractController
{
private $session;
function __construct(SessionInterface $session)
{
$this->session = $session;
}
/**
* #Route("/dashboard", name="app_dashboard")
*/
function dashboard()
{
return $this->render('account/dashboard.html.twig', []);
}
}
security.yaml
security:
providers:
users:
entity:
class: 'App\Entity\User'
property: 'email'
encoders:
App\Entity\User:
algorithm: 'auto'
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: lazy
guard:
authenticators:
- App\Security\LoginFormAuthenticator
logout:
path: app_logout
access_control:
- { path: ^/dashboard, roles: ROLE_USER }
User.php
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
* #UniqueEntity(fields={"email"}, message="There is already an account with this email")
*/
class User implements UserInterface, \Serializable
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=2048, nullable=true)
*/
private $email;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=4096, nullable=false)
*/
private $password;
/**
* #var string
*
* #ORM\Column(name="salt", type="string", length=2048, nullable=true)
*/
private $salt;
////////
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getSalt(): ?string
{
return $this->salt;
}
public function setSalt(string $salt): self
{
$this->salt = $salt;
return $this;
}
/**
* #inheritDoc
*/
public function getUsername()
{
return $this->email;
}
/**
* #inheritDoc
*/
public function getRoles()
{
return array('ROLE_USER');
}
/**
* #inheritDoc
*/
public function eraseCredentials()
{
}
/**
* #inheritDoc
*/
public function equals(UserInterface $user)
{
return $this->id === $user->getId();
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
return serialize(array(
$this->id,
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
) = unserialize($serialized);
}
public function isEqualTo(UserInterface $user)
{
if (!$user instanceof User) {
return false;
}
if ($this->password !== $user->getPassword()) {
return false;
}
if ($this->salt !== $user->getSalt()) {
return false;
}
if ($this->email !== $user->getEmail()) {
return false;
}
return true;
}
}
Edit..
When the exception is commented in, the logs say:
INFO
19:32:37
request Matched route "app_login".
Show context
INFO
19:32:38
security Guard authentication successful!
Show context
CRITICAL
19:32:38
request Uncaught PHP Exception Exception: "TODO: provide a valid redirect inside /var/www/src/Security/LoginFormAuthenticator.php" at /var/www/src/Security/LoginFormAuthenticator.php line 87
And when the redirect is there the logs say:
19:30:24
security Checking for guard authentication credentials.
Hide context
[▼
"firewall_key" => "main"
"authenticators" => 1
]
19:30:24
security Checking support on guard authenticator.
Hide context
[▼
"firewall_key" => "main"
"authenticator" => "App\Security\LoginFormAuthenticator"
]
19:30:24
security Guard authenticator does not support the request.
Hide context
[▼
"firewall_key" => "main"
"authenticator" => "App\Security\LoginFormAuthenticator"
]
..edit - and same behaviour in both http & https.
I wanted to leave a comment for you, but my reputation is less than 50 so I'll write my comment in the answer.
The support method is deprecated.
Don't use it anymore.
Use the following example:
LoginFormAuthenticator.php
public function getCredentials(Request $request)
{
$isLoginSubmit = 'user_login' === $request->attributes->get('_route') && $request->isMethod('POST');
if(!$isLoginSubmit) {
return;
}
//...other codes
}
protected function getDefaultSuccessRedirectUrl()
{
return $this->urlGenerator->generate('user_dashboard');
}
UserController.php
<?php
namespace AppBundle\Controller\User;
use AppBundle\Form\User\UserManager\UserLoginForm;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
/**
* User controller.
*
* #Route("User")
*/
class UserController extends Controller
{
/**
* #Route("/login", name="user_login")
*/
public function loginAction()
{
$authenticationUtils = $this->get('security.authentication_utils');
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
$form = $this->createForm(UserLoginForm::class, ["_username" => $lastUsername]);
return $this->render('User/login.html.twig', [
'form' => $form->createView(),
'error' => $error,
]);
}
/**
* #Route("/logout", name="user_logout")
*/
public function logoutAction()
{
throw new \Exception('User logout');
}
/**
* #Route("/dashboard", name="user_dashboard")
*/
public function dashboardAction()
{
return $this->render('User/dashboard.html.twig');
}
}
security.yaml
Provider and pattern is required:
firewalls:
//...other firewalls
main:
anonymous: ~
pattern: ^/user
provider: users
access_control:
- { path: ^/user/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/user, roles: ROLE_USER }
Hope to help you.
Leave a comment with any feedback.
The problem was that the user wasn't being refreshed, the Guard Authenticator was doing exactly what it should. Stripping back the User Entity to the following fixed it.
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
* #UniqueEntity(fields={"email"}, message="There is already an account with this email")
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255, unique=true)
*/
private $email;
/**
* #ORM\Column(type="string", length=255)
*/
private $password;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getUsername()
{
return $this->email;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
////
public function getRoles()
{
return [
'ROLE_USER'
];
}
public function getSalt()
{
}
public function eraseCredentials()
{
}
}

Symfony 3.3 The autoloader expected class

I've got a problem with my Symfony project. I'm trying to put a form login authenticator and for that I need to create a repository of my user class. However, i've got that error :
The autoloader expected class "AppBundle\Repository\UserRepository" to be defined in file "C:\wamp64\www\Symfony\vendor\composer/../../src\AppBundle\Repository\UserRepository.php". The file was found but the class was not in it, the class name or namespace probably has a typo.
Here's my UserRepository class :
<?php
namespace AppBundle\Repository;
use Doctrine\Bundle\DoctrineBundle\Repository\EntityRepository;
use AppBundle\Entity\User;
class UserRepository extends EntityRepository
{
public function findAllOrderedByName()
{
return $this->getEntityManager()
->createQuery(
'SELECT u FROM AppBundle:User u ORDER BY u.username ASC'
)
->getResult();
}
}
?>
My User entity :
<?php
namespace AppBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* #ORM\Table(name="user")
*/
class User implements UserInterface
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", unique=true)
*/
private $username;
/**
* #ORM\Column(type="string", unique=true)
*/
private $apiKey;
/**
* #ORM\Column(type="string", length=64)
*/
private $password;
public function getId()
{
return $this->id;
}
public function getUsername()
{
return $this->username;
}
public function getPassword()
{
return $this->password;
}
public function getApiKey()
{
return $this->apiKey;
}
public function getRoles()
{
return array('ROLE_USER');
}
public function getSalt()
{
}
public function eraseCredentials()
{
}
public function setUsername($_username)
{
$this->username = $_username;
}
public function setPassword($_password)
{
$this->password = $_password;
}
public function setId($_id)
{
return $this->id = $_id;
}
public function setApiKey($_apiKey)
{
return $this->apiKey = $_apiKey;
}
}
?>
My security.yml :
security:
encoders:
AppBundle\Entity\User:
algorithm: bcrypt
providers:
our_db_provider:
entity:
class: AppBundle:User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
guard:
authenticators:
- AppBundle\Security\LoginFormAuthenticator
And finally my FormLoginAuthenticator :
<?php
namespace AppBundle\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use AppBundle\Repository\UserRepository;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
private $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function supports(Request $request)
{
return $request->attributes->get('_route') === 'app_login'
&& $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
return [
'username' => $request->request->get('username'),
'password' => $request->request->get('password'),
];
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
return $this->userRepository->findOneBy(['username' => $credentials['username']]);
}
public function checkCredentials($credentials, UserInterface $user)
{
die($user);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
// todo
}
protected function getLoginUrl()
{
// TODO: Implement getLoginUrl() method.
}
}
?>
Thanks you by advance for helping me. Also, if you have a better solution to build my form authenticator, it will be very nice.

Symfony 2.3 - Validator.yml within my bundle not working

I have 2 bundles, 1 works with the validation.yml file and one does not.
Both bundles are set up exactly the same, i have googled high and low and i cannot seem to understand why.
I have created a form type here:
<?php
namespace Brs\UserBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class Usertype extends AbstractType
{
protected $fname;
protected $lname;
protected $email;
protected $mobile;
protected $active;
protected $mentor;
protected $initialized;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('fname','text',array('label'=>'First Name'))
->add('lname','text',array('label'=>'Last Name'))
->add('email','email',array('label'=>'Email'))
->add('mobile','text',array('label'=>'Mobile'))
->add('active','choice',array(
'label'=>'Active?',
'choices'=>array('0'=>'No','1'=>'Yes'),
'expanded'=>true,
'multiple'=>false
))
->add('mentor','choice',array(
'label'=>'Mentor?',
'choices'=>array('0'=>'No','1'=>'Yes'),
'expanded'=>true,
'multiple'=>false
))
->add('Add Player?','submit');
}
public function getName()
{
return 'user';
}
public function setFname($fname)
{
$this->fname = $fname;
return $this;
}
public function getFname()
{
return $this->fname;
}
public function setLname($lname)
{
$this->lname = $lname;
return $this;
}
public function getLname()
{
return $this->lname;
}
public function setEmail($email)
{
$this->email = $email;
return $this;
}
public function getEmail()
{
return $this->email;
}
public function setMobile($mobile)
{
$this->mobile = $mobile;
return $this;
}
public function getMobile()
{
return $this->mobile;
}
public function setActive($active)
{
$this->active = $active;
return $this;
}
public function getActive()
{
return $this->active;
}
public function setMentor($mentor)
{
$this->mentor = $mentor;
return $this;
}
public function getMentor()
{
return $this->mentor;
}
public function setInitialized($initialized)
{
$this->initialized = $initialized;
return $this;
}
public function getInitialized()
{
return $this->initialized;
}
}
This is my validation.yml in bundle/Resources/config:
Brs\UserBundle\Form\Type\UserType:
properties:
fname:
- NotBlank: ~
- Length:
min: 3
lname:
- NotBlank: ~
- Length:
min: 3
email:
- NotBlank: ~
- Length:
min: 3
This is my controller that builds the form from the class and renders it renders fine:
<?php
namespace Brs\UserBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
// use Symfony\Component\HttpFoundation\Response;
// use Brs\UserBundle\Entity\User;
use Brs\UserBundle\Form\Type\UserType;
class UserController extends Controller{
public function indexAction(Request $request){
$user = new UserType();
$form = $this->createForm(new UserType(),$user);
$form->handleRequest($request);
if($form->isValid()){
echo 'yes';
}
//print_r($user);
return $this->render(
'BrsUserBundle:User:userForm.html.twig',
array(
'title'=>"Add Player",
'form'=>$form->createView()
));
}
}
?>
In app/config/config.yml i have these params set for validation:
validation: { enabled: true, enable_annotations: false }
Now when I submit the form with no data the request hits the controller and the method
$form->isValid();
is called, this returns true.
This should return false as my constraints in my validation.yml file do not allow blank fields to be processed and should trigger the form to render the field errors within the template.
I am clearly missing something here, Any help would be greatly appreciated.
Thanks
Adam
You should not validate your UserType, but the User object itself. Also the second argument of createForm() needs to be a User object.
$user = new User();
$form = $this->createForm(new UserType(),$user);
validation.yml:
Brs\UserBundle\Entity\User:
properties:
# constraint list

Categories