Security voters are one of the most powerful tools for managing permissions
in Symfony. They allow you to centralize authorization logic in a reusable class
that Symfony automatically calls whenever you use isGranted()
in your PHP
code or Twig templates.
The Symfony profiler provides a detailed overview of which voters participated in the decision for the current request and their results (grant, deny, or abstain). This makes it easier to debug most voter-related issues. However, figuring out why a voter denied access has often required digging through custom logic.
That's why in Symfony 7.3, security voters can now explain their vote. This
new feature introduces a $vote
argument to the VoterInterface::vote()
and Voter::voteOnAttribute()
methods, allowing voters to add reasons
explaining their decisions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
namespace App\Security\Voter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter as BaseVoter;
// ...
class BlogCommentVoter extends BaseVoter
{
protected function supports(string $attribute, mixed $subject): bool
{
// ...
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token, ?Vote $vote = null): bool
{
// ...
if (...) {
$vote?->addReason(sprintf('The post (id: %d) no longer accepts comments', $post->getId()));
return false;
}
if (...) {
$vote?->addReason(sprintf('The logged in user (username: %s) was banned from adding new comments', $user->getUsername()));
return false;
}
return true;
}
}
These reasons are then displayed in the exception pages, the Symfony profiler, and log messages, making it much easier to understand and debug access control issues in your application.
That's a neat new feature. Thanks!
Thanks Nicolas <3
That's great!
This is awesome enhancement, thanks! ❤️