vendor/hslavich/oneloginsaml-bundle/DependencyInjection/Security/Factory/SamlFactory.php line 82

Open in your IDE?
  1. <?php
  2. namespace Hslavich\OneloginSamlBundle\DependencyInjection\Security\Factory;
  3. use Hslavich\OneloginSamlBundle\Event\UserCreatedEvent;
  4. use Hslavich\OneloginSamlBundle\Event\UserModifiedEvent;
  5. use Hslavich\OneloginSamlBundle\EventListener\User\UserCreatedListener;
  6. use Hslavich\OneloginSamlBundle\EventListener\User\UserModifiedListener;
  7. use Hslavich\OneloginSamlBundle\Security\Authentication\Provider\SamlProvider;
  8. use Hslavich\OneloginSamlBundle\Security\Authentication\Token\SamlTokenFactoryInterface;
  9. use Hslavich\OneloginSamlBundle\Security\Firewall\SamlListener;
  10. use Hslavich\OneloginSamlBundle\Security\Http\Authentication\SamlAuthenticationSuccessHandler;
  11. use Hslavich\OneloginSamlBundle\Security\Http\Authenticator\SamlAuthenticator;
  12. use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AuthenticatorFactoryInterface;
  13. use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface;
  14. use Symfony\Component\Config\Definition\Builder\NodeDefinition;
  15. use Symfony\Component\DependencyInjection\ChildDefinition;
  16. use Symfony\Component\DependencyInjection\ContainerBuilder;
  17. use Symfony\Component\DependencyInjection\ContainerInterface;
  18. use Symfony\Component\DependencyInjection\Reference;
  19. use Symfony\Component\Security\Http\HttpUtils;
  20. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  21. class SamlFactory implements SecurityFactoryInterfaceAuthenticatorFactoryInterface
  22. {
  23.     protected $options = [
  24.         'check_path' => 'saml_acs',
  25.         'use_forward' => false,
  26.         'require_previous_session' => false,
  27.         'login_path' => 'saml_login',
  28.         'username_attribute' => null,
  29.         'use_attribute_friendly_name' => false,
  30.         'user_factory' => null,
  31.         'token_factory' => null,
  32.         'persist_user' => false,
  33.         'success_handler' => SamlAuthenticationSuccessHandler::class,
  34.     ];
  35.     protected $defaultSuccessHandlerOptions = [
  36.         'always_use_default_target_path' => false,
  37.         'default_target_path' => '/',
  38.         'login_path' => 'saml_login',
  39.         'target_path_parameter' => '_target_path',
  40.         'use_referer' => false,
  41.     ];
  42.     protected $defaultFailureHandlerOptions = [
  43.         'failure_path' => null,
  44.         'failure_forward' => false,
  45.         'login_path' => 'saml_login',
  46.         'failure_path_parameter' => '_failure_path',
  47.     ];
  48.     public function addConfiguration(NodeDefinition $node): void
  49.     {
  50.         $builder $node->children();
  51.         $builder
  52.             ->scalarNode('provider')->end()
  53.             ->booleanNode('remember_me')->defaultTrue()->end()
  54.             ->scalarNode('success_handler')->end()
  55.             ->scalarNode('failure_handler')->end()
  56.         ;
  57.         foreach (array_merge($this->options$this->defaultSuccessHandlerOptions$this->defaultFailureHandlerOptions) as $name => $default) {
  58.             if (\is_bool($default)) {
  59.                 $builder->booleanNode($name)->defaultValue($default);
  60.             } else {
  61.                 $builder->scalarNode($name)->defaultValue($default);
  62.             }
  63.         }
  64.     }
  65.     final public function addOption(string $name$default null): void
  66.     {
  67.         $this->options[$name] = $default;
  68.     }
  69.     public function create(ContainerBuilder $containerstring $id, array $configstring $userProviderId, ?string $defaultEntryPointId): array
  70.     {
  71.         trigger_deprecation('hslavich/oneloginsaml-bundle''2.1''Usage of security authentication listener is deprecated, option "security.enable_authenticator_manager" should be set to true.');
  72.         $authProviderId $this->createAuthProvider($container$id$config$userProviderId);
  73.         $listenerId $this->createListener($container$id$config);
  74.         $this->createUserListeners($container$id$config);
  75.         // add remember-me aware tag if requested
  76.         if ($config['remember_me']) {
  77.             $listenerDefinition $container->getDefinition($listenerId);
  78.             $listenerDefinition->addTag('security.remember_me_aware', ['id' => $id'provider' => $userProviderId]);
  79.         }
  80.         $entryPointId $this->createEntryPoint($container$id$config);
  81.         return [$authProviderId$listenerId$entryPointId];
  82.     }
  83.     public function getPosition(): string
  84.     {
  85.         return 'pre_auth';
  86.     }
  87.     public function getPriority(): int
  88.     {
  89.         return -10;
  90.     }
  91.     public function getKey(): string
  92.     {
  93.         return 'saml';
  94.     }
  95.     public function createAuthenticator(ContainerBuilder $containerstring $firewallName, array $configstring $userProviderId): string
  96.     {
  97.         $authenticatorId 'security.authenticator.saml.'.$firewallName;
  98.         $authenticator = (new ChildDefinition(SamlAuthenticator::class))
  99.             ->replaceArgument(0, new Reference(HttpUtils::class))
  100.             ->replaceArgument(1, new Reference($userProviderId))
  101.             ->replaceArgument(3, new Reference($this->createAuthenticationSuccessHandler($container$firewallName$config)))
  102.             ->replaceArgument(4, new Reference($this->createAuthenticationFailureHandler($container$firewallName$config)))
  103.             ->replaceArgument(5array_intersect_key($config$this->options))
  104.         ;
  105.         if ($config['user_factory']) {
  106.             $authenticator->replaceArgument(6, new Reference($config['user_factory']));
  107.         }
  108.         $container->setDefinition($authenticatorId$authenticator);
  109.         $this->createUserListeners($container$firewallName$config);
  110.         return $authenticatorId;
  111.     }
  112.     protected function createAuthProvider(ContainerBuilder $container$id$config$userProviderId): string
  113.     {
  114.         $providerId 'security.authentication.provider.saml.'.$id;
  115.         $definition $container->setDefinition($providerId, new ChildDefinition(SamlProvider::class))
  116.             ->setArguments([
  117.                 new Reference($userProviderId),
  118.                 new Reference(EventDispatcherInterface::class, ContainerInterface::NULL_ON_INVALID_REFERENCE),
  119.             ])
  120.         ;
  121.         if ($config['user_factory']) {
  122.             $definition->addMethodCall('setUserFactory', [new Reference($config['user_factory'])]);
  123.         }
  124.         $factoryId $config['token_factory'] ?: SamlTokenFactoryInterface::class;
  125.         $definition->addMethodCall('setTokenFactory', [new Reference($factoryId)]);
  126.         return $providerId;
  127.     }
  128.     protected function createListener(ContainerBuilder $containerstring $id, array $config): string
  129.     {
  130.         $listenerId $this->getListenerId();
  131.         $listener = (new ChildDefinition($listenerId))
  132.             ->replaceArgument(4$id)
  133.             ->replaceArgument(5, new Reference($this->createAuthenticationSuccessHandler($container$id$config)))
  134.             ->replaceArgument(6, new Reference($this->createAuthenticationFailureHandler($container$id$config)))
  135.             ->replaceArgument(7array_intersect_key($config$this->options))
  136.         ;
  137.         $listenerId .= '.'.$id;
  138.         $container->setDefinition($listenerId$listener);
  139.         return $listenerId;
  140.     }
  141.     protected function getListenerId(): string
  142.     {
  143.         return SamlListener::class;
  144.     }
  145.     protected function createEntryPoint(ContainerBuilder $containerstring $id, array $config): ?string
  146.     {
  147.         $entryPointId 'security.authentication.form_entry_point.'.$id;
  148.         $container
  149.             ->setDefinition($entryPointId, new ChildDefinition('security.authentication.form_entry_point'))
  150.             ->addArgument(new Reference(HttpUtils::class))
  151.             ->addArgument($config['login_path'])
  152.             ->addArgument($config['use_forward'])
  153.         ;
  154.         return $entryPointId;
  155.     }
  156.     protected function createAuthenticationSuccessHandler(ContainerBuilder $containerstring $id, array $config): string
  157.     {
  158.         $successHandlerId $this->getSuccessHandlerId($id);
  159.         $options array_intersect_key($config$this->defaultSuccessHandlerOptions);
  160.         $successHandler $container->setDefinition($successHandlerId, new ChildDefinition('security.authentication.custom_success_handler'));
  161.         $successHandler->replaceArgument(0, new Reference($config['success_handler']));
  162.         $successHandler->replaceArgument(1$options);
  163.         $successHandler->replaceArgument(2$id);
  164.         return $successHandlerId;
  165.     }
  166.     protected function createAuthenticationFailureHandler(ContainerBuilder $containerstring $id, array $config): string
  167.     {
  168.         $id $this->getFailureHandlerId($id);
  169.         $options array_intersect_key($config$this->defaultFailureHandlerOptions);
  170.         if (isset($config['failure_handler'])) {
  171.             $failureHandler $container->setDefinition($id, new ChildDefinition('security.authentication.custom_failure_handler'));
  172.             $failureHandler->replaceArgument(0, new Reference($config['failure_handler']));
  173.             $failureHandler->replaceArgument(1$options);
  174.         } else {
  175.             $failureHandler $container->setDefinition($id, new ChildDefinition('security.authentication.failure_handler'));
  176.             $failureHandler->addMethodCall('setOptions', [$options]);
  177.         }
  178.         return $id;
  179.     }
  180.     protected function getSuccessHandlerId(string $id): string
  181.     {
  182.         return 'security.authentication.success_handler.'.$id.'.'.str_replace('-''_'$this->getKey());
  183.     }
  184.     protected function getFailureHandlerId(string $id): string
  185.     {
  186.         return 'security.authentication.failure_handler.'.$id.'.'.str_replace('-''_'$this->getKey());
  187.     }
  188.     protected function createUserListeners(ContainerBuilder $containerstring $firewallName, array $config): void
  189.     {
  190.         $container->setDefinition('hslavich_onelogin_saml.user_created_listener.'.$firewallName, new ChildDefinition(UserCreatedListener::class))
  191.             ->replaceArgument(1$config['persist_user'])
  192.             ->addTag('hslavich.saml_user_listener')
  193.             ->addTag('kernel.event_listener', ['event' => UserCreatedEvent::class])
  194.         ;
  195.         $container->setDefinition('hslavich_onelogin_saml.user_modified_listener.'.$firewallName, new ChildDefinition(UserModifiedListener::class))
  196.             ->replaceArgument(1$config['persist_user'])
  197.             ->addTag('hslavich.saml_user_listener')
  198.             ->addTag('kernel.event_listener', ['event' => UserModifiedEvent::class])
  199.         ;
  200.     }
  201. }