Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Security] Removed anonymous in the new security system #36574

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions 18 UPGRADE-5.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,24 @@ Routing
SecurityBundle
--------------

* Deprecated `anonymous: lazy` in favor of `lazy: true`

*Before*
```yaml
security:
firewalls:
main:
anonymous: lazy
```

*After*
```yaml
security:
firewalls:
main:
anonymous: true
lazy: true
```
* Marked the `AnonymousFactory`, `FormLoginFactory`, `FormLoginLdapFactory`, `GuardAuthenticationFactory`,
`HttpBasicFactory`, `HttpBasicLdapFactory`, `JsonLoginFactory`, `JsonLoginLdapFactory`, `RememberMeFactory`, `RemoteUserFactory`
and `X509Factory` as `@internal`. Instead of extending these classes, create your own implementation based on
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto
->scalarNode('entry_point')->end()
->scalarNode('provider')->end()
->booleanNode('stateless')->defaultFalse()->end()
->booleanNode('lazy')->defaultFalse()->end()
->scalarNode('context')->cannotBeEmpty()->end()
->arrayNode('logout')
->treatTrueLike([])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use Symfony\Component\Config\Definition\Builder\NodeDefinition;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Parameter;
Expand Down Expand Up @@ -46,16 +47,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,

public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
{
if (null === $config['secret']) {
$config['secret'] = new Parameter('container.build_hash');
}

$authenticatorId = 'security.authenticator.anonymous.'.$firewallName;
$container
->setDefinition($authenticatorId, new ChildDefinition('security.authenticator.anonymous'))
->replaceArgument(0, $config['secret']);

return $authenticatorId;
throw new InvalidConfigurationException(sprintf('The authenticator manager no longer has "anonymous" security. Please remove this option under the "%s" firewall'.($config['lazy'] ? ' and add "lazy: true"' : '').'.', $firewallName));
}

public function getPosition()
Expand All @@ -76,7 +68,7 @@ public function addConfiguration(NodeDefinition $builder)
->then(function ($v) { return ['lazy' => true]; })
->end()
->children()
->booleanNode('lazy')->defaultFalse()->end()
->booleanNode('lazy')->defaultFalse()->setDeprecated('symfony/security-bundle', '5.1', 'Using "anonymous: lazy" to make the firewall lazy is deprecated, use "lazy: true" instead.')->end()
->scalarNode('secret')->defaultNull()->end()
->end()
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ public function load(array $configs, ContainerBuilder $container)

if ($this->authenticatorManagerEnabled = $config['enable_authenticator_manager']) {
$loader->load('security_authenticator.xml');

// The authenticator system no longer has anonymous tokens. This makes sure AccessListener
// and AuthorizationChecker do not throw AuthenticationCredentialsNotFoundException when no
// token is available in the token storage.
$container->getDefinition('security.access_listener')->setArgument(4, false);
$container->getDefinition('security.authorization_checker')->setArgument(4, false);
$container->getDefinition('security.authorization_checker')->setArgument(5, false);
} else {
$loader->load('security_legacy.xml');
}
Expand Down Expand Up @@ -269,7 +276,8 @@ private function createFirewalls(array $config, ContainerBuilder $container)
list($matcher, $listeners, $exceptionListener, $logoutListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId);

$contextId = 'security.firewall.map.context.'.$name;
$context = new ChildDefinition($firewall['stateless'] || empty($firewall['anonymous']['lazy']) ? 'security.firewall.context' : 'security.firewall.lazy_context');
$isLazy = !$firewall['stateless'] && (!empty($firewall['anonymous']['lazy']) || $firewall['lazy']);
$context = new ChildDefinition($isLazy ? 'security.firewall.lazy_context' : 'security.firewall.context');
$context = $container->setDefinition($contextId, $context);
$context
->replaceArgument(0, new IteratorArgument($listeners))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,6 @@
<argument type="service" id="property_accessor" on-invalid="null" />
</service>

<service id="security.authenticator.anonymous"
class="Symfony\Component\Security\Http\Authenticator\AnonymousAuthenticator"
abstract="true">
<argument type="abstract">secret</argument>
<argument type="service" id="security.untracked_token_storage" />
</service>

<service id="security.authenticator.remember_me"
class="Symfony\Component\Security\Http\Authenticator\RememberMeAuthenticator"
abstract="true">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ security:
firewalls:
secure:
pattern: ^/
anonymous: lazy
anonymous: ~
lazy: true
stateless: false
guard:
authenticators:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ security:
check_path: /login_check
default_target_path: /profile
logout: ~
anonymous: lazy
anonymous: ~
lazy: true

# This firewall is here just to check its the logout functionality
second_area:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,30 @@ class AuthorizationChecker implements AuthorizationCheckerInterface
private $accessDecisionManager;
private $authenticationManager;
private $alwaysAuthenticate;
private $exceptionOnNoToken;

public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, AccessDecisionManagerInterface $accessDecisionManager, bool $alwaysAuthenticate = false)
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, AccessDecisionManagerInterface $accessDecisionManager, bool $alwaysAuthenticate = false, bool $exceptionOnNoToken = true)
{
$this->tokenStorage = $tokenStorage;
$this->authenticationManager = $authenticationManager;
$this->accessDecisionManager = $accessDecisionManager;
$this->alwaysAuthenticate = $alwaysAuthenticate;
$this->exceptionOnNoToken = $exceptionOnNoToken;
}

/**
* {@inheritdoc}
*
* @throws AuthenticationCredentialsNotFoundException when the token storage has no authentication token
* @throws AuthenticationCredentialsNotFoundException when the token storage has no authentication token and $exceptionOnNoToken is set to true
*/
final public function isGranted($attribute, $subject = null): bool
{
if (null === ($token = $this->tokenStorage->getToken())) {
throw new AuthenticationCredentialsNotFoundException('The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL.');
if ($this->exceptionOnNoToken) {
throw new AuthenticationCredentialsNotFoundException('The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL.');
}

return false;
}

if ($this->alwaysAuthenticate || !$token->isAuthenticated()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ public function testVoteWithoutAuthenticationToken()
$this->authorizationChecker->isGranted('ROLE_FOO');
}

public function testVoteWithoutAuthenticationTokenAndExceptionOnNoTokenIsFalse()
{
$authorizationChecker = new AuthorizationChecker($this->tokenStorage, $this->authenticationManager, $this->accessDecisionManager, false, false);

$this->assertFalse($authorizationChecker->isGranted('ROLE_FOO'));
}

/**
* @dataProvider isGrantedProvider
*/
Expand Down

This file was deleted.

49 changes: 38 additions & 11 deletions 49 src/Symfony/Component/Security/Http/Firewall/AccessListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,21 @@
*/
class AccessListener extends AbstractListener
{
const PUBLIC_ACCESS = 'PUBLIC_ACCESS';

private $tokenStorage;
private $accessDecisionManager;
private $map;
private $authManager;
private $exceptionOnNoToken;

public function __construct(TokenStorageInterface $tokenStorage, AccessDecisionManagerInterface $accessDecisionManager, AccessMapInterface $map, AuthenticationManagerInterface $authManager)
public function __construct(TokenStorageInterface $tokenStorage, AccessDecisionManagerInterface $accessDecisionManager, AccessMapInterface $map, AuthenticationManagerInterface $authManager, bool $exceptionOnNoToken = true)
{
$this->tokenStorage = $tokenStorage;
$this->accessDecisionManager = $accessDecisionManager;
$this->map = $map;
$this->authManager = $authManager;
$this->exceptionOnNoToken = $exceptionOnNoToken;
}

/**
Expand All @@ -52,18 +56,18 @@ public function supports(Request $request): ?bool
[$attributes] = $this->map->getPatterns($request);
$request->attributes->set('_access_control_attributes', $attributes);

return $attributes && [AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY] !== $attributes ? true : null;
return $attributes && ([AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY] !== $attributes && [self::PUBLIC_ACCESS] !== $attributes) ? true : null;
}

/**
* Handles access authorization.
*
* @throws AccessDeniedException
* @throws AuthenticationCredentialsNotFoundException
* @throws AuthenticationCredentialsNotFoundException when the token storage has no authentication token and $exceptionOnNoToken is set to true
*/
public function authenticate(RequestEvent $event)
{
if (!$event instanceof LazyResponseEvent && null === $token = $this->tokenStorage->getToken()) {
if (!$event instanceof LazyResponseEvent && null === ($token = $this->tokenStorage->getToken()) && $this->exceptionOnNoToken) {
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.');
}

Expand All @@ -76,8 +80,26 @@ public function authenticate(RequestEvent $event)
return;
}

if ($event instanceof LazyResponseEvent && null === $token = $this->tokenStorage->getToken()) {
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.');
if ($event instanceof LazyResponseEvent) {
$token = $this->tokenStorage->getToken();
}

if (null === $token) {
if ($this->exceptionOnNoToken) {
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.');
}

if ([AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY] === $attributes) {
trigger_deprecation('symfony/security-http', '5.1', 'Using "IS_AUTHENTICATED_ANONYMOUSLY" in your access_control rules when using the authenticator Security system is deprecated, use "PUBLIC_ACCESS" instead.');

return;
}

if ([self::PUBLIC_ACCESS] === $attributes) {
return;
}

throw $this->createAccessDeniedException($request, $attributes);
}

if (!$token->isAuthenticated()) {
Expand All @@ -86,11 +108,16 @@ public function authenticate(RequestEvent $event)
}

if (!$this->accessDecisionManager->decide($token, $attributes, $request, true)) {
$exception = new AccessDeniedException();
$exception->setAttributes($attributes);
$exception->setSubject($request);

throw $exception;
throw $this->createAccessDeniedException($request, $attributes);
}
}

private function createAccessDeniedException(Request $request, array $attributes)
{
$exception = new AccessDeniedException();
$exception->setAttributes($attributes);
$exception->setSubject($request);

return $exception;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ private function handleAccessDeniedException(ExceptionEvent $event, AccessDenied

try {
$insufficientAuthenticationException = new InsufficientAuthenticationException('Full authentication is required to access this resource.', 0, $exception);
$insufficientAuthenticationException->setToken($token);
if (null !== $token) {
$insufficientAuthenticationException->setToken($token);
}

$event->setResponse($this->startAuthentication($event->getRequest(), $insufficientAuthenticationException));
} catch (\Exception $e) {
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.