Skip to content
Advertisement

CSRF Invalid because of two entities in the registration process

I have two entities and one form for the registration process.When I add csrf token it probably works for one of them, not for both.

<form action="" method="post" class="registerForm" id="registerForm" novalidate>
    <div class="form-row">
        <div class="form-group col-lg-6">
            <input type="text" class="form-control inner-blue-shadow" name="company[name]" id="companyName" placeholder="Име на фирма" required/>
            <div class="invalid-feedback"></div>
            <div class="valid-feedback"></div>
        </div>
        <div class="form-group col-lg-6">
            <input type="text" class="form-control inner-blue-shadow" name="company[bulstat]" id="bulstat" placeholder="Булстат" required/>
            <div class="invalid-feedback"></div>
            <div class="valid-feedback"></div>
        </div>
    </div>
    <div class="form-group">
        <input type="text" class="form-control inner-blue-shadow" name="user[username]" id="username" placeholder="Потребителско име" required/>
        <div class="invalid-feedback"></div>
        <div class="valid-feedback"></div>
    </div>
    <div class="form-group">
        <input type="email" class="form-control inner-blue-shadow" name="user[email]" id="email" placeholder="Имейл адрес" required/>

    </div>
    <div class="form-group">
        <input type="password" class="form-control inner-blue-shadow" name="user[password]" id="password" placeholder="Парола" required/>
        <div class="invalid-feedback"></div>
        <div class="valid-feedback"></div>
    </div>
    {{ form_row(form._token) }}
    <div class="text-center"><button type="submit" id="registerButton">Create account</button></div>
</form>

The output is: “user__token” so as far as I can see it generates it with the exception that is affects only one of the two entities – User and it does not work for the other one.

When I remove the company fields everything works like a charm.

The forms are:

1.User

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $schools = $this->schoolRepository->findAll();

    $builder
        ->add('username', TextType::class)
        ->add('email', EmailType::class)
        ->add('password', PasswordType::class)
}

/**
 * {@inheritdoc}
 */
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'AppBundleEntityUser',
        'csrf_protection' => true,
        'csrf_field_name' => '_token',
        'csrf_token_id'   => 'task_item'
    ));
}

2.Company:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('name', TextType::class);
    $builder->add('bulstat', TextType::class);
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'AppBundleEntityCompany',
        'csrf_protection' => true,
        'csrf_field_name' => '_token',
        'csrf_token_id'   => 'task_item'
    ));
}

The controller where forms are being created:

$company = new Company();
$companyForm = $this->createForm(CompanyType::class, $company);
$companyForm->handleRequest($request);

$user = new User();
$userForm = $this->createForm(UserType::class, $user);
$userForm->handleRequest($request);

How could I fix it?

Advertisement

Answer

This is basically a question of how to combine two entities into one form. There are other questions that address this but some are a bit old and out of date. This question is also an example of not taking advantage of what Symfony has to offer and working a bit harder than the developer has to.

Specifically, Symfony deals with csrf out of the box and requires no special configuration. You can do more stuff with it but it is easier to start with a default working implementation and then tweak if necessary. In a similar fashion, twig has a default rendering of a form. After the form is working you can then use various styling tools to make it look pretty.

Start by simplifying your EntityType classes and adding a RegisterType:

class UserType extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => User::class,
        ));
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('username', TextType::class)
            ->add('email', EmailType::class)
            ->add('password', PasswordType::class);
    }
}
class CompanyType extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Company::class,
        ));
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class)
            ->add('bulstat', TextType::class);
    }
}
class RegisterType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('user', UserType::class)
            ->add('company', CompanyType::class)
            ->add('register', SubmitType::class);
    }
}

Now adjust the controller code and use the default form rendering:

    public function register(Request $request)
    {
        $user = new User();
        $company = new Company();
        $register = ['user' => $user, 'company' => $company];

        $form = $this->createForm(RegisterType::class, $register);

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            dump($user);
            dump($company);
        }

        return $this->render('register.html.twig',['form' => $form->createView()]);
    }
# register.html.twig
{%% extends 'base.html.twig' %%}
{%% block body %%}
    <h1>Register</h1>
    {{ form(form) }}
{%% endblock %%}

At this point you should have a working form. You can then add validation and persistence as well as making the form look nice.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement