Customising your Access Decision Stategy


In this video you will learn how to customise the Access Decision Strategy, which in turn allows you to influence the outcome of Symfony's security voting process.

This is a more advanced topic, and not something you will likely need to change for most of your voting needs. However, it is nice to know this feature exists, and it's really not that hard to implement.

The typical situation when using voters is that you would have one voter for each resource / class you are protecting. If this is your circumstance then the following will be of no use to you.

However, if you have multiple voters for a given resource, then you may wish to customise the outcome of the ballot / vote.

This is achieved by changing the Access Decision Strategy.

There are three access decision strategies available in Symfony:

  • affirmative (default) - This grants access as soon as there is one voter granting access;
  • consensus - This grants access if there are more voters granting access than denying;
  • unanimous - This only grants access once all voters grant access.

Changing your access decision strategy is as easy as updating security.yml:

# app/config/security.yml
security:
    access_decision_manager:
        strategy: consensus

One thing to note is that this configures the access decision strategy for your entire application. As best I understand it currently, there is no way to specify individual strategies for certain voters.

Affirmative

An interesting way in which the affirmative strategy works is that if, for example, you had two voters for a given resource, and one returns ACCESS_DENIED, and the other returns ACCESS_GRANTED, then you would be granted access.

Changing the priority of your event listeners makes no difference here. Each voter will be called but the overall outcome is that as long as at least one voter grants access, then access will be granted. More on listener priorities here (scroll down a bit).

Consensus

Perhaps even more interesting though is the outcome of consensus. If you have three voters and two return ACCESS_GRANTED then the consensus is that you should be granted access. That seems fair enough.

But what if you only have two voters, and one returns ACCESS_GRANTED, whilst the other returns ACCESS_DENIED? My assumption was that in this instance, you would be denied. However, in reality, you will get ACCESS_GRANTED.

If you want to deny access, you need to update your security.yml accordingly:

# app/config/security.yml
security:
    access_decision_manager:
        strategy: consensus 
        allow_if_equal_granted_denied:  false  # default = true

This is something that should be tested with an acceptance test.

Unanimous

Lastly, unaminous will deny access unless every single voter that is taking part in the vote returns ACCESS_GRANTED.

The only caveat to this is that any voters returning ACCESS_ABSTAIN will be ignored.

So, if any single voter returns ACCESS_DENIED, then access will be denied, even if you had 100 voters and 99 granted access and 1 denied, the vote result would be ACCESS_DENIED.

Edge Case - All Abstain

What would happen if every voter in the vote returned ACCESS_ABSTAIN?

Well, by default, access would be denied in this case.

You can change this if you need to, by updating security.yml:

# app/config/security.yml
security:
    access_decision_manager:
        allow_if_all_abstain:  true  # default = false

That covers the three available options inside the access_decision_manager section of the security.yml file.

If you would like to see all the available options, be sure to check out the Security configuration reference.

As ever, be sure to test your security logic with the appropriate level of unit, integration, and acceptance tests. It's fairly easy to make mistakes or get unexpected outcomes as these are parts of your system that likely / hopefully you rarely need to configure.

Episodes

# Title Duration
1 The Application Setup and Introduction 06:17
2 Using Symfony's Security Annotation 06:43
3 Simple Security Voters 08:28
4 Customising your Access Decision Stategy 04:58