Solved it myself. As @Chausser said access control via query params is not possible in security.yml, so I've created a voter for that.
// src/Your/Bundle/Security/Voter/PreviewAccessVoter.php
namespace Your\Bundle\Security\Voter;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* voter that denies access if user has not the required role
* to access urls with preview query param set true
*/
class PreviewAccessVoter implements VoterInterface
{
protected $requestStack;
protected $requiredRole;
public function __construct(RequestStack $requestStack, $requiredRole)
{
$this->requestStack = $requestStack;
$this->requiredRole = $requiredRole;
}
public function supportsAttribute($attribute)
{
return true;
}
public function supportsClass($class)
{
return true;
}
public function vote(TokenInterface $token, $object, array $attributes)
{
if(filter_var($this->requestStack->getCurrentRequest()->query->get('preview'), FILTER_VALIDATE_BOOLEAN))
{
foreach($token->getRoles() as $role) {
if($this->requiredRole === $role->getRole()) {
return VoterInterface::ACCESS_GRANTED;
}
}
return VoterInterface::ACCESS_DENIED;
}
return VoterInterface::ACCESS_ABSTAIN;
}
}
Add voter as (hidden) service
# src/Your/Bundle/Resources/config/services.yml
# preview voter that denies access for users without the required role
security.access.preview.voter:
class: Your\BundleBundle\Security\Voter\PreviewAccessVoter
arguments: [ @request_stack , ROLE_ADMIN ]
tags: [ { name: security.voter } ]
public: false
Changing the Access Decision Strategy
# app/config/security.yml
access_decision_manager:
strategy: unanimous # can be: affirmative, unanimous or consensus
see: http://symfony.com/doc/current/cookbook/security/voters.html as a reference
https://github.com/symfony/Security/blob/master/Core/Authorization/Voter/RoleVoter.php might also be helpful