Skip to content

Commit 122a935

Browse files
committed
feature #31189 [Security] Add IS_IMPERSONATOR, IS_ANONYMOUS and IS_REMEMBERED (HeahDude)
This PR was merged into the 5.1-dev branch. Discussion ---------- [Security] Add IS_IMPERSONATOR, IS_ANONYMOUS and IS_REMEMBERED | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | symfony/symfony#29848 | License | MIT | Doc PR | symfony/symfony-docs#11487 This continues work of @HeahDude and finally finishes one of the code PRs I've been working on during the ⭐️ EUFOSSA Hackathon. Changes --- The PRs modifies some of the attributes used by the `AuthenticatedVoter`: * New `IS_IMPERSONATOR`, `IS_ANONYMOUS` and `IS_REMEMBERED` attributes are introduced to indicate the user either impersonated, anonymous or rembered. * <s>`IS_AUTHENTICATED_ANONYMOUSLY` actually meant "is authenticated, either anonymous or fully". As this is confusing, it is replaced by `IS_AUTHENTICATED`.</s> * <s>All `is_*()` functions in expressions are deprecated in favor of `is_granted('IS_*')`. It's not worth duplicating the `AuthenticatedVoter` logic in two places now we have shorter `IS_*` attributes</s> **Before** ```php if ($authorizationChecker->isGranted('ROLE_PREVIOUS_ADMIN')) { // ... } ``` <s> ```yaml security: # ... access_control: - { path: ^/protected, roles: 'IS_AUTHENTICATED_ANONYMOUSLY' } ``` </s> **After** ```php if ($authorizationChecker->isGranted('IS_IMPERSONATOR')) { // ... } ``` <s> ```yaml security: # ... access_control: - { path: ^/protected, roles: 'IS_AUTHENTICATED' } ``` </s> <s>Discussion --- The only thing I'm wondering is how we combine this with the `is_authenticated()` expression function: https://github.com/symfony/symfony/blob/98929dc2927c59ba3e36b5547f2eae6316aa4740/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguageProvider.php#L33-L37 As you can see, the `IS_AUTHENTICATED` attribute and `is_authenticated()` expression function do not have the same meaning. Should we somehow deprecate the current behavior of `is_authenticated()` or should we find another name for `IS_AUTHENTICATED` (that would be a shame imo).</s> Commits ------- 6c522a7d98 Added IS_ANONYMOUS, IS_REMEMBERED, IS_IMPERSONATOR
2 parents d2ea483 + 80ab897 commit 122a935

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

Authorization/Voter/AuthenticatedVoter.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Security\Core\Authorization\Voter;
1313

1414
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
15+
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
1516
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
1617

1718
/**
@@ -28,6 +29,9 @@ class AuthenticatedVoter implements VoterInterface
2829
const IS_AUTHENTICATED_FULLY = 'IS_AUTHENTICATED_FULLY';
2930
const IS_AUTHENTICATED_REMEMBERED = 'IS_AUTHENTICATED_REMEMBERED';
3031
const IS_AUTHENTICATED_ANONYMOUSLY = 'IS_AUTHENTICATED_ANONYMOUSLY';
32+
const IS_ANONYMOUS = 'IS_ANONYMOUS';
33+
const IS_IMPERSONATOR = 'IS_IMPERSONATOR';
34+
const IS_REMEMBERED = 'IS_REMEMBERED';
3135

3236
private $authenticationTrustResolver;
3337

@@ -45,7 +49,10 @@ public function vote(TokenInterface $token, $subject, array $attributes)
4549
foreach ($attributes as $attribute) {
4650
if (null === $attribute || (self::IS_AUTHENTICATED_FULLY !== $attribute
4751
&& self::IS_AUTHENTICATED_REMEMBERED !== $attribute
48-
&& self::IS_AUTHENTICATED_ANONYMOUSLY !== $attribute)) {
52+
&& self::IS_AUTHENTICATED_ANONYMOUSLY !== $attribute
53+
&& self::IS_ANONYMOUS !== $attribute
54+
&& self::IS_IMPERSONATOR !== $attribute
55+
&& self::IS_REMEMBERED !== $attribute)) {
4956
continue;
5057
}
5158

@@ -68,6 +75,18 @@ public function vote(TokenInterface $token, $subject, array $attributes)
6875
|| $this->authenticationTrustResolver->isFullFledged($token))) {
6976
return VoterInterface::ACCESS_GRANTED;
7077
}
78+
79+
if (self::IS_REMEMBERED === $attribute && $this->authenticationTrustResolver->isRememberMe($token)) {
80+
return VoterInterface::ACCESS_GRANTED;
81+
}
82+
83+
if (self::IS_ANONYMOUS === $attribute && $this->authenticationTrustResolver->isAnonymous($token)) {
84+
return VoterInterface::ACCESS_GRANTED;
85+
}
86+
87+
if (self::IS_IMPERSONATOR === $attribute && $token instanceof SwitchUserToken) {
88+
return VoterInterface::ACCESS_GRANTED;
89+
}
7190
}
7291

7392
return $result;

Tests/Authorization/Voter/AuthenticatedVoterTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ public function getVoteTests()
4949
['fully', ['IS_AUTHENTICATED_FULLY'], VoterInterface::ACCESS_GRANTED],
5050
['remembered', ['IS_AUTHENTICATED_FULLY'], VoterInterface::ACCESS_DENIED],
5151
['anonymously', ['IS_AUTHENTICATED_FULLY'], VoterInterface::ACCESS_DENIED],
52+
53+
['fully', ['IS_ANONYMOUS'], VoterInterface::ACCESS_DENIED],
54+
['remembered', ['IS_ANONYMOUS'], VoterInterface::ACCESS_DENIED],
55+
['anonymously', ['IS_ANONYMOUS'], VoterInterface::ACCESS_GRANTED],
56+
57+
['fully', ['IS_IMPERSONATOR'], VoterInterface::ACCESS_DENIED],
58+
['remembered', ['IS_IMPERSONATOR'], VoterInterface::ACCESS_DENIED],
59+
['anonymously', ['IS_IMPERSONATOR'], VoterInterface::ACCESS_DENIED],
60+
['impersonated', ['IS_IMPERSONATOR'], VoterInterface::ACCESS_GRANTED],
5261
];
5362
}
5463

@@ -58,6 +67,8 @@ protected function getToken($authenticated)
5867
return $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
5968
} elseif ('remembered' === $authenticated) {
6069
return $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken')->setMethods(['setPersistent'])->disableOriginalConstructor()->getMock();
70+
} elseif ('impersonated' === $authenticated) {
71+
return $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken')->disableOriginalConstructor()->getMock();
6172
} else {
6273
return $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken')->setConstructorArgs(['', ''])->getMock();
6374
}

0 commit comments

Comments
 (0)