Skip to content

Commit

Permalink
CC-17232 Introduced session validation for agent. (#9629)
Browse files Browse the repository at this point in the history
CC-17232 Introduced session validation for agent.
  • Loading branch information
romanhavrylko committed Nov 8, 2022
1 parent f90883b commit 62688dc
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 13 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"php": ">=8.0",
"spryker/application-extension": "^1.0.0",
"spryker/kernel": "^3.52.0",
"spryker/security-extension": "^1.0.0",
"spryker/security-extension": "^1.1.0",
"spryker/symfony": "^3.8.0",
"spryker/validator-extension": "^1.0.0"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ public function mergeFirewall(string $firewallName, array $configuration)
{
$this->assertNotFrozen();

if (array_key_exists($firewallName, $this->mergableFirewalls)) {
$configuration += $this->mergableFirewalls[$firewallName];
}

$this->mergableFirewalls[$firewallName] = $configuration;

return $this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,21 +314,41 @@ class SecurityApplicationPlugin extends AbstractPlugin implements ApplicationPlu
protected const SERVICE_VALIDATOR = 'validator';

/**
* @var array
* @var list<string>
*/
protected const POSITIONS = ['logout', 'pre_auth', 'guard', 'form', 'http', 'remember_me', 'anonymous', 'customer_session_validator'];
protected const DEFAULT_AUTHENTICATION_LISTENER_FACTORY_TYPES = [
'logout',
'pre_auth',
'guard',
'form',
'http',
'remember_me',
'anonymous',
'customer_session_validator',
];

/**
* @var array
* @var array<array<string>>
*/
protected $securityRoutes = [];
protected array $securityRoutes = [];

/**
* @var \Spryker\Shared\SecurityExtension\Configuration\SecurityConfigurationInterface|null
*/
protected $securityConfiguration;

/**
* @var list<string>
*/
protected array $authenticationListenerFactoryTypes = [];

/**
* {@inheritDoc}
* - Executes the stack of {@link \Spryker\Shared\SecurityExtension\Dependency\Plugin\SecurityPluginInterface} plugins.
* - Executes the stack of {@link \Spryker\Shared\SecurityExtension\Dependency\Plugin\SecurityAuthenticationListenerFactoryTypeExpanderPluginInterface} plugins.
*
* @api
*
* @param \Spryker\Service\Container\ContainerInterface $container
*
* @return \Spryker\Service\Container\ContainerInterface
Expand Down Expand Up @@ -612,8 +632,8 @@ protected function getFirewallMap(ContainerInterface $container): FirewallMapInt
}

$factories = [];
foreach (static::POSITIONS as $position) {
$factories[$position] = [];
foreach ($this->getAuthenticationListenerFactoryTypes() as $authenticationListenerFactoryType) {
$factories[$authenticationListenerFactoryType] = [];
}

foreach ($firewallConfiguration as $type => $options) {
Expand All @@ -631,16 +651,16 @@ protected function getFirewallMap(ContainerInterface $container): FirewallMapInt
throw new LogicException(sprintf('The "%s" authentication entry is not registered.', $type));
}
$options['stateless'] = $stateless;
[$providerId, $listenerId, $entryPointId, $position] = $container->get('security.authentication_listener.factory.' . $type)($firewallName, $options);
[$providerId, $listenerId, $entryPointId, $authenticationListenerFactoryType] = $container->get('security.authentication_listener.factory.' . $type)($firewallName, $options);
if ($entryPointId !== null) {
$entryPoint = $entryPointId;
}
$factories[$position][] = $listenerId;
$factories[$authenticationListenerFactoryType][] = $listenerId;
$providers[] = $providerId;
}

foreach (static::POSITIONS as $position) {
foreach ($factories[$position] as $listener) {
foreach ($this->getAuthenticationListenerFactoryTypes() as $authenticationListenerFactoryType) {
foreach ($factories[$authenticationListenerFactoryType] as $listener) {
$listeners[] = $listener;
}
}
Expand Down Expand Up @@ -784,7 +804,7 @@ protected function addChannelListener(ContainerInterface $container): ContainerI
*/
protected function addAuthenticationListenerFactories(ContainerInterface $container): ContainerInterface
{
foreach (['logout', 'pre_auth', 'guard', 'form', 'http', 'remember_me', 'anonymous'] as $type) {
foreach ($this->getAuthenticationListenerFactoryTypes() as $type) {
$entryPoint = $this->getEntryPoint($type);

$container->set('security.authentication_listener.factory.' . $type, $container->protect(function ($firewallName, $options) use ($type, $container, $entryPoint) {
Expand Down Expand Up @@ -1720,4 +1740,30 @@ protected function createRequestMatcher(ContainerInterface $container, string $n

return $requestMatcher;
}

/**
* @return list<string>
*/
protected function getAuthenticationListenerFactoryTypes(): array
{
if ($this->authenticationListenerFactoryTypes === []) {
$this->initializeAuthenticationListenerFactoryTypes();
}

return $this->authenticationListenerFactoryTypes;
}

/**
* @return void
*/
protected function initializeAuthenticationListenerFactoryTypes(): void
{
$this->authenticationListenerFactoryTypes = static::DEFAULT_AUTHENTICATION_LISTENER_FACTORY_TYPES;

foreach ($this->getFactory()->getSecurityAuthenticationListenerFactoryTypeExpanderPlugins() as $securityAuthenticationListenerFactoryTypeExpanderPlugin) {
$this->authenticationListenerFactoryTypes = $securityAuthenticationListenerFactoryTypeExpanderPlugin->expand(
$this->authenticationListenerFactoryTypes,
);
}
}
}
43 changes: 42 additions & 1 deletion src/Spryker/Yves/Security/SecurityDependencyProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,32 @@ class SecurityDependencyProvider extends AbstractBundleDependencyProvider
*/
public const PLUGINS_SECURITY = 'PLUGINS_SECURITY';

/**
* @var string
*/
public const PLUGINS_SECURITY_AUTHENTICATION_LISTENER_FACTORY_TYPE_EXPANDER = 'PLUGINS_SECURITY_AUTHENTICATION_LISTENER_FACTORY_TYPE_EXPANDER';

/**
* @param \Spryker\Yves\Kernel\Container $container
*
* @return \Spryker\Yves\Kernel\Container
* @return \Spryker\Yves\Kernel\Container
*/
public function provideDependencies(Container $container): Container
{
$container = parent::provideDependencies($container);

$container = $this->addSecurityPlugins($container);
$container = $this->addSecurityAuthenticationListenerFactoryTypeExpanderPlugins($container);

return $container;
}

/**
* @param \Spryker\Yves\Kernel\Container $container
*
* @return \Spryker\Yves\Kernel\Container
*/
protected function addSecurityPlugins(Container $container): Container
{
$container->set(static::PLUGINS_SECURITY, function () {
return $this->getSecurityPlugins();
Expand All @@ -42,4 +61,26 @@ protected function getSecurityPlugins(): array
{
return [];
}

/**
* @param \Spryker\Yves\Kernel\Container $container
*
* @return \Spryker\Yves\Kernel\Container
*/
protected function addSecurityAuthenticationListenerFactoryTypeExpanderPlugins(Container $container): Container
{
$container->set(static::PLUGINS_SECURITY_AUTHENTICATION_LISTENER_FACTORY_TYPE_EXPANDER, function () {
return $this->getSecurityAuthenticationListenerFactoryTypeExpanderPlugins();
});

return $container;
}

/**
* @return list<\Spryker\Shared\SecurityExtension\Dependency\Plugin\SecurityAuthenticationListenerFactoryTypeExpanderPluginInterface>
*/
protected function getSecurityAuthenticationListenerFactoryTypeExpanderPlugins(): array
{
return [];
}
}
8 changes: 8 additions & 0 deletions src/Spryker/Yves/Security/SecurityFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,12 @@ public function createSecurityConfiguration(): SecurityConfiguration
{
return new SecurityConfiguration();
}

/**
* @return list<\Spryker\Shared\SecurityExtension\Dependency\Plugin\SecurityAuthenticationListenerFactoryTypeExpanderPluginInterface>
*/
public function getSecurityAuthenticationListenerFactoryTypeExpanderPlugins(): array
{
return $this->getProvidedDependency(SecurityDependencyProvider::PLUGINS_SECURITY_AUTHENTICATION_LISTENER_FACTORY_TYPE_EXPANDER);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ class SecurityConfigurationTest extends Unit
*/
protected const FIREWALL_SECONDARY = 'secondary';

/**
* @var string
*/
protected const TEST_FIREWALL_CONFIGURATION = 'test';

/**
* @var string
*/
protected const TEST_FIREWALL_CONFIGURATION_2 = 'test_2';

/**
* @var string
*/
protected const TEST_FIREWALL_CONFIGURATION_3 = 'test_3';

/**
* @return void
*/
Expand Down Expand Up @@ -89,6 +104,36 @@ public function testMergeFirewallWhichIsNotConfiguredWillThrowAnException(): voi
$securityConfiguration->getConfiguration();
}

/**
* @return void
*/
public function testMergeFirewallShouldNotRemoveAlreadyAddedConfiguration(): void
{
// Arrange
$securityConfiguration = (new SecurityConfiguration())->addFirewall(static::FIREWALL_MAIN, [
static::TEST_FIREWALL_CONFIGURATION => static::TEST_FIREWALL_CONFIGURATION,
]);

// Act
$securityConfiguration->mergeFirewall(static::FIREWALL_MAIN, [
static::TEST_FIREWALL_CONFIGURATION_2 => static::TEST_FIREWALL_CONFIGURATION_2,
]);
$securityConfiguration->mergeFirewall(static::FIREWALL_MAIN, [
static::TEST_FIREWALL_CONFIGURATION_3 => static::TEST_FIREWALL_CONFIGURATION_3,
]);

// Assert
$firewalls = $securityConfiguration->getConfiguration()->getFirewalls();

$this->assertArrayHasKey(static::FIREWALL_MAIN, $firewalls);
$this->assertCount(1, $securityConfiguration->getFirewalls());
$this->assertSame([
static::TEST_FIREWALL_CONFIGURATION => static::TEST_FIREWALL_CONFIGURATION,
static::TEST_FIREWALL_CONFIGURATION_3 => static::TEST_FIREWALL_CONFIGURATION_3,
static::TEST_FIREWALL_CONFIGURATION_2 => static::TEST_FIREWALL_CONFIGURATION_2,
], $firewalls[static::FIREWALL_MAIN]);
}

/**
* @return void
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Exception;
use LogicException;
use Spryker\Shared\Security\Configuration\SecurityConfiguration;
use Spryker\Shared\SecurityExtension\Dependency\Plugin\SecurityAuthenticationListenerFactoryTypeExpanderPluginInterface;
use Spryker\Yves\Security\Plugin\Application\SecurityApplicationPlugin;
use SprykerTest\Yves\Security\Fixtures\TokenAuthenticator;
use Symfony\Component\HttpFoundation\Request;
Expand Down Expand Up @@ -38,6 +39,16 @@
*/
class SecurityApplicationPluginTest extends Unit
{
/**
* @var string
*/
protected const TEST_SECURITY_AUTHENTICATION_LISTENER_FACTORY_TYPE = 'test_security_type';

/**
* @var string
*/
protected const TEST_SECURITY_AUTHENTICATION_LISTENER_FACTORY = 'security.authentication_listener.factory.test_security_type';

/**
* @uses \Spryker\Yves\Security\Plugin\Application\SecurityApplicationPlugin::SERVICE_SECURITY_AUTHORIZATION_CHECKER
*
Expand Down Expand Up @@ -639,6 +650,35 @@ public function testLastErrorReturnSecurityAuthenticationError(): void
$this->assertSame('security error', $securityError);
}

/**
* @return void
*/
public function testProvideShouldExecuteSecurityAuthenticationListenerFactoryTypeExpanderPluginStack(): void
{
// Arrange
$securityPositionExpanderPluginMock = $this->getMockBuilder(SecurityAuthenticationListenerFactoryTypeExpanderPluginInterface::class)
->getMock();

$securityPositionExpanderPluginMock
->method('expand')
->willReturn([static::TEST_SECURITY_AUTHENTICATION_LISTENER_FACTORY_TYPE]);

$factoryMock = $this->tester->mockFactoryMethod('getSecurityAuthenticationListenerFactoryTypeExpanderPlugins', [
$securityPositionExpanderPluginMock,
]);

$securityApplicationPlugin = new SecurityApplicationPlugin();
$securityApplicationPlugin->setFactory($factoryMock);

$container = $this->tester->getContainer();

// Act
$securityApplicationPlugin->provide($container);

// Assert
$this->assertTrue($container->has(static::TEST_SECURITY_AUTHENTICATION_LISTENER_FACTORY));
}

/**
* @return void
*/
Expand Down

0 comments on commit 62688dc

Please sign in to comment.