Securing the Symfony UX Autocomplete component
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.
- Add the generated autocomplete URL to the
firewalls
section inconfig\packages\security.yaml
:
security:
firewalls:
admin:
context: admin
pattern:
- '/admin(?:/.*)?$'
- '/autocomplete/company_autocomplete_field$'
- Add the generated autocomplete URL to the
access_control
section inconfig\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!