Home / Symfony / New in Symfony 7.4: Security Voter Improvements

New in Symfony 7.4: Security Voter Improvements

Security voters are one of Symfony’s most powerful tools for managing
permissions. They let you centralize your authorization logic and reuse it
throughout your application. In Symfony 7.4, we’re introducing several new
features for them.

Twig Functions for Access Decisions


Florent Destremau
Contributed by
Florent Destremau
in
#61379

Symfony already provides the is_granted() and is_granted_for_user()
Twig functions so you can check permissions with voters in your templates.
These functions return a boolean value indicating whether the current or
specified user has the given security attribute.

In Symfony 7.4, we’re adding two new Twig functions: access_decision() and
access_decision_for_user(). They return an AccessDecision object, a DTO
that stores the access verdict, the collection of votes, the resulting message
(for example, “Access granted” or a custom access-denied message), and more.

{% set voter_decision = access_decision('post_edit', post) %}
{% if voter_decision.isGranted() %}
    {# ... #}
{% else %}
    {# before showing voter messages to end users, make sure it's safe to do so #}
    <p>{{ voter_decision.message }}</p>
{% endif %}

Add Metadata to Vote Objects


Eltharin
Contributed by
Eltharin
in
#60085

In Symfony 7.3, we introduced the Vote object as part of a feature that
explains security voter decisions. In Symfony 7.4, we’re extending it so you can
attach arbitrary metadata to each vote. Inside your security voter, use the
extraData property of the Vote object to add any custom value:

use SymfonyComponentSecurityCoreAuthorizationVoterVote;
use SymfonyComponentSecurityCoreAuthorizationVoterVoter;
// ...

class BlogPostVoter extends Voter
{
    // ...

    protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
    {
        // ...

        // values can be of any type, not only strings
        $vote->extraData['some_key'] = 'some value';
    }
}

You can use this new feature, for example, when defining a custom access decision strategy.
By default, Symfony votes can only grant, deny, or abstain, and all votes
have equal weight. In a custom strategy, you could assign a score or weight to
each vote (for example, $vote->extraData['score'] = 10;) and use that value
when aggregating results:

// src/Security/MyCustomAccessDecisionStrategy.php
use SymfonyComponentSecurityCoreAuthorizationStrategyAccessDecisionStrategyInterface;

class MyCustomAccessDecisionStrategy implements AccessDecisionStrategyInterface
{
    public function decide(Traversable $results, $accessDecision = null): bool
    {
        $score = 0;

        foreach ($results as $key => $result) {
            $vote = $accessDecision->votes[$key];
            if (array_key_exists('score', $vote->extraData)) {
                $score += $vote->extraData['score'];
            } else {
                $score += $vote->result;
            }
        }

        // ...
    }
}


Sponsor the Symfony project.
Tagged:

Leave a Reply

Your email address will not be published. Required fields are marked *