Skip to main content

Securing the Symfony UX Autocomplete component

· 2 min read
Stephan Hochdörfer
Head of IT Business Operations

The Symfony UX Autocomplete component makes integrating an autocomplete element in your forms easy.

The component takes care of the frontend experience and adds the logic to retrieve the data from the backend API.

By default, the API endpoint is accessible to anyone. For some situations, this is not ideal. Luckily, the component has a security option. Pass the role that should be able to access the endpoint via a security configuration attribute:

<?php

declare(strict_types=1);

namespace App\Form\Field;

use App\Entity\Company;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\UX\Autocomplete\Form\AsEntityAutocompleteField;
use Symfony\UX\Autocomplete\Form\BaseEntityAutocompleteType;

#[AsEntityAutocompleteField]
class CompanyAutocompleteField extends AbstractType
{
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'class' => Company::class,
'searchable_fields' => ['name'],
'label' => 'app.form..company',
'choice_label' => 'name',
'multiple' => false,
'security' => 'ROLE_ADMIN',
]);
}

public function getParent(): string
{
return BaseEntityAutocompleteType::class;
}
}

Testing the form in my application revealed that the autocomplete element does not return any data. Looking in the networking tab reveals why: The generated API endpoint returns a "403 Forbidden" error.

But why?

It took me a while to find the source of the problem. The documentation doesn't state it, but the component does not modify the firewall configuration. Somehow, I felt this would be done automatically.

To ensure the security settings are correctly configured, you need to make two changes in the security configuration of your Symfony application.

  1. Add the generated autocomplete URL to the firewalls section in config\packages\security.yaml:
security:
firewalls:
admin:
context: admin
pattern:
- '/admin(?:/.*)?$'
- '/autocomplete/company_autocomplete_field$'
  1. Add the generated autocomplete URL to the access_control section in config\packages\security.yaml:
security:
access_control:
- { path: ^/autocomplete/company_autocomplete_field, roles: ROLE_ADMIN }

Since the entity used for the Autocomplete field is called Company the URL generated by the Autocomplete component is /autocomplete/company_autocomplete_field.

After clearing the cache, I tested the form again, and it worked!