ApiPlatform - implement security authorization on subresource route

1.3k views Asked by At

I'm using Symfony5 and ApiPlatform

I have a User entity and a Product entity.

I want to list all my user's products through a subressource, to do so I've implemented my user class as follow :


/**
 * @ApiResource(
 *     attributes={
 *          "normalization_context"={"groups"={"user:read", "user:list"}},
 *          "denormalization_context"={"groups"={"user:put", "user:post"}}
 *     },
 *    subresourceOperations={
 *         "api_users_consultations_get_subresource"={
 *             "method"="GET",
 *             "security"="is_granted('ROLE_ADMIN')"
 *         }
 *    },
 *    collectionOperations={
 *        "get"={
 *              "method"="GET",
 *              "security"="is_granted('ROLE_ADMIN')",
 *              "normalization_context"={"groups"={"user:list"}}
 *          },
 *        "post"={
 *              "method"="POST",
 *              "security_post_denormalize"="is_granted('POST', object)",
 *              "denormalization_context"={"groups"={"user:post"}}
 *        }
 *    },
 *    itemOperations={
 *        "get"={
 *          "method"="GET",
 *          "security"="is_granted('GET', object)",
 *          "normalization_context"={"groups"={"user:read"}}
 *         }
 *    }
 * )
 * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=false)
 * @ORM\Entity(repositoryClass=UserRepository::class)
 */
class User
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     * @Groups({"user:read", "user:list"})
     *
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity=Product::class, mappedBy="user")
     * @ApiSubresource()
     */
    private $product;
}

It does create a route /users/{id}/products and return me what I want.

The part where I'm blocking is when I want to add authorization to this route:

  • ROLE_ADMIN can access this route
  • ROLE_USER who own the ressource can access it
  • All the other roles will receive FORBIDDEN

To do so I've followed the doc : https://api-platform.com/docs/core/subresources/#using-serialization-groups

  • Added subresourceOperations to @ApiSubresource annotation
  • recovered the name of my grenerated route api_users_consultations_get_subresource through the bin/console debug:router command
  • and simply set a security=is_granted('ROLE_ADMIN') method like for other operations.
  • or security=is_granted('SUB_LIST', object) to hit the voter

but when I run my tests I get 200 where I should receive 403, the UserVoter or ProductVoter are not triggered nor the is_granted('ROLE_ADMIN') rule.

As if the subresourceOperations annotation wasn't recognize by the ApiPlatform.

I've also tried changing the name of the operation from api_users_consultations_get_subresource to :

  • consultations_get_subresource
  • api_consultations_get_subresource
  • clients_get_subresource
  • api_clients_get_subresource

and different other variants as I saw on Github it solved the issue in some cases (like here https://github.com/api-platform/api-platform/issues/1581#issuecomment-662503549) but it has not worked for me.

So I'm wondering is there something I havn't done to implement it correctly ?

Is it a known issue of ApiPlatform ?

Does anyone see where my logic is failing ?

Is there another way to setup security on subresource routes ?

Are there more docs on security realted to subresource? I have not find a lot of material on this particular subject

0

There are 0 answers