Access Denied Error Symfony with roles without prefix 'ROLE_'

298 Views Asked by At

Good morning, I want to update my symfony 2.8 application to version 5.4. I am having problems with the is_granted function of symfony.

My connected user has all the roles in the token (classic roles + custom roles). Custom roles are linked to the company and each user of a company inherits the roles of the company.

I add all the roles in the token however when I put an is_granted on a rest class, I get an access denied. Could you tell me if I forgot something please?

My REST class with the is_granted function :

/**
 * TrainingSession controller.
 * @RouteResource("Training")
 * @Security("is_granted('MODULE_TRAINING')")
 */
class TrainingSessionRESTController extends BaseRESTController
{

My token with the corresponding role :

  "ROLE_HR"
  "ROLE_DEBUG"
  "ROLE_PANEL"
  "ROLE_USER"
  "ROLE_MANAGER"
  "MODULE_LIBRARY"
  "MODULE_EXPENSE_REPORT"
  "MODULE_TRAINING"
  "MODULE_ANNUAL_REVIEW"
  "MODULE_PRO_REVIEW"
  "MODULE_COMPANY_CHART"
  "MODULE_COMPANY_CONTACT"
  "MODULE_COMPANY_DOCUMENT"
  "MODULE_CALENDAR"
  "MODULE_FOLDER"
  "MODULE_TIME_MANAGEMENT"
  "MODULE_EMPLOYEE_MEDICAL"
  "MODULE_REPORT"

I tried to override the class which adds the "ROLE_" prefix. This is the RoleVoter class but without success, the prefix still seems to be taken into account.

This is my custom RoleVoter and I tried to set the prefix to empty but without success :

namespace WORD\CoreBundle\Voter;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * RoleVoter votes if any attribute starts with a given prefix.
 *
 * @author Fabien Potencier <[email protected]>
 */
class CustomVoter implements CacheableVoterInterface
{
    private $prefix;

    public function __construct(string $prefix = 'ROLE_')
    {
        $this->prefix = 'ROLE_';
    }

    /**
     * {@inheritdoc}
     */
    public function vote(TokenInterface $token, $subject, array $attributes)
    {
        
        $result = VoterInterface::ACCESS_ABSTAIN;
        $roles = $this->extractRoles($token);

        foreach ($attributes as $attribute) {
            if (!\is_string($attribute) || !str_starts_with($attribute, $this->prefix)) {
                continue;
            }

            if ('ROLE_PREVIOUS_ADMIN' === $attribute) {
                trigger_deprecation('symfony/security-core', '5.1', 'The ROLE_PREVIOUS_ADMIN role is deprecated and will be removed in version 6.0, use the IS_IMPERSONATOR attribute instead.');
            }

            $result = VoterInterface::ACCESS_DENIED;
            foreach ($roles as $role) {
                if ($attribute === $role) {
                    return VoterInterface::ACCESS_GRANTED;
                }
            }
        }

        return $result;
    }

    public function supportsAttribute(string $attribute): bool
    {
        return str_starts_with($attribute, $this->prefix);
    }

    public function supportsType(string $subjectType): bool
    {
        return true;
    }

    protected function extractRoles(TokenInterface $token)
    {
        return $token->getRoleNames();
    }
}

I can't rename all my roles by adding the prefix 'ROLE_' because my roles are specified in the front

1

There are 1 best solutions below

0
abadjanier On

this is my configuration and works for me:

security.access.simple_role_voter:
    public: true
    class: Symfony\Component\Security\Core\Authorization\Voter\RoleVoter
    arguments: [ '' ]

in this way i don't have any restriction for role prefixes.

i'm in 5.4 version