API Platform: Voters reference
In a nutshell
You can use Symfony Voter classes to implement access control checks for different operations on your entities.
1. Create Voter class for entity
You’ll want to create a dedicated Voter class for each entity that you want to implement access control checks for. Here’s an example for a Book
entity:
<?php
// api/src/Security/Voter/BookVoter.php
namespace App\Security\Voter;
use App\Entity\Book;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
class BookVoter extends Voter
{
private $security = null;
public function __construct(Security $security)
{
$this->security = $security;
}
protected function supports($attribute, $subject): bool
{
$supportsAttribute = in_array($attribute, ['BOOK_CREATE', 'BOOK_READ', 'BOOK_EDIT', 'BOOK_DELETE']);
$supportsSubject = $subject instanceof Book;
return $supportsAttribute && $supportsSubject;
}
/**
* @param string $attribute
* @param Book $subject
* @param TokenInterface $token
* @return bool
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
/** ... check if the user is anonymous ... **/
switch ($attribute) {
case 'BOOK_CREATE':
if ( $this->security->isGranted(Role::ADMIN) ) { return true; } // only admins can create books
break;
case 'BOOK_READ':
/** ... other autorization rules ... **/
}
return false;
}
}
1. Specify supports
condition
Use supports
method is to determine whether the current voter class should apply to a given operation.
In the above example, we want BookVoter
to only apply if the operation is one of BOOK_CREATE
, BOOK_READ
, BOOK_EDIT
, or BOOK_DELETE
and the subject is an instance of Book
.
2. Specify permissions checks
The voteOnAttribute
method specifies the actual permission checks. You can use a switch statement to handle the different operations (e.g., BOOK_READ
, BOOK_CREATE
, etc).
2. Apply voter to API resources / operations
Once you’ve created your Voter class, you can apply it at the operation level:
<?php
// api/src/Entity/Book.php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
#[ApiResource(
attributes: ["security" => "is_granted('ROLE_USER')"],
collectionOperations: [
"get",
"post" => [ "security_post_denormalize" => "is_granted('BOOK_CREATE', object)" ],
],
itemOperations: [
"get" => [ "security" => "is_granted('BOOK_READ', object)" ],
"put" => [ "security" => "is_granted('BOOK_EDIT', object)" ],
"delete" => [ "security" => "is_granted('BOOK_DELETE', object)" ],
],
)]
class Book
{
// ...
Other notes
- You cannot use Voters on collection GET operations. You must use extensions instead (also see this note).
- Avoid using both the
attributes: ["security" => ".."]
andsecurity_post_denormalize
together. If you need to usesecurity_post_denormalize
, specifysecurity
only at the operation level. - If you use Voters on POST methods, you must use something like
"post" = { "security_post_denormalize" = "is_granted('BOOK_CREATE', object)" }
so that the voter receives both the$attribute
and$subject
.
Sources
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment