Rvanlaak
Rvanlaak

Reputation: 3085

Check if other user is granted than the active one

We have some frontend logic that uses voters to check whether users can show documents. That same logic should be applied in the backend, the difference is that over there an admin user is the active one in the TokenStorage.

if (false === $this->authorizationChecker->isGranted('show', $document)) {
   continue;
}

The same voters should be used, but with another user object (the owner of the document). Could not find any documentation on temporarily changing the authenticated user for the voters.

Although the authorization docs mention setToken, I can not imagine that overwriting the token would be the way to go. So, is there a Symfony service we can use to apply the voting on our own user? One that is not currently active in the TokenStorage (yet)?

Upvotes: 1

Views: 1780

Answers (2)

yceruto
yceruto

Reputation: 9575

For RoleVoter decendents you can do it exchanging the token stored and restoring it back after check the permissions:

$tokenStorage = $this->get('security.token_storage');
$authorizationChecker = $this->get('security.authorization_checker');

// gets the user owner of the document
$owner = $document->getOwner();

// create new token for owner user/roles
$ownerToken = new AnonymousToken(null, $owner, $owner->getRoles());

// save current token to restore later
$prevToken = $tokenStorage->getToken();

// change the current token
$tokenStorage->setToken($ownerToken);

// checking now the owner roles
if ($authorizationChecker->isGranted('show', $document)) {
    // ...
}

// restore the previous token
$tokenStorage->setToken($prevToken);

These changes only affect the access decision in this moment. For reusability you can create a new AuthorizationChecker/Service to use the user instance as 3rd argument of isGranted method, something like this:

$user = $document->getOwner();

if ($this->get('my_authorization_checker')->isGranted('show', $document, $user)) {
    // ...
}

this method will check first if the user is provided or not, if so changes the token, else do nothing and checks the logged user.

Upvotes: 3

Dmitry Malyshenko
Dmitry Malyshenko

Reputation: 3051

Try to make another authorizationChecker service

<service id="app.token_storage" class="Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage" />

<service id="app.authorization_checker" class="Symfony\Component\Security\Core\Authorization\AuthorizationChecker">
      <argument type="service" id="app.token_storage"/>
      <argument type="service" id="security.authentication.manager"/>
      <argument type="service" id="security.access.decision_manager"/>
      <argument>false</argument>
</service>

And then in controller

$this->get('security.token_storage')->setToken($yourTokenToBeChecked);
$this->get('security.authorization_checker')->isGranted('show', $document);

Upvotes: 1

Related Questions