From 2af58f6f7fe0f76e6a927c69362c59f86f7dc210 Mon Sep 17 00:00:00 2001 From: Nicholas Ruunu Date: Mon, 9 Jul 2018 11:19:47 +0200 Subject: [PATCH] Add configuration for CSRF protection --- DependencyInjection/Configuration.php | 1 + DependencyInjection/HappyrAuth0Extension.php | 6 +++++ Resources/config/security.yml | 1 + Security/EntryPoint/SSOEntryPoint.php | 23 +++++++++++++++----- Security/Firewall/SSOListener.php | 22 ++++++++++++++----- 5 files changed, 43 insertions(+), 10 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 4867ecc..b76a0db 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -28,6 +28,7 @@ public function getConfigTreeBuilder() ->booleanNode('security')->defaultTrue()->info( "Whether or not the SecurityBundle integration should be enabled. Set to false if and only if your app does not use SecurityBundle." )->end() + ->booleanNode('csrf_protection')->defaultTrue()->end() ->end(); return $treeBuilder; diff --git a/DependencyInjection/HappyrAuth0Extension.php b/DependencyInjection/HappyrAuth0Extension.php index e107325..34116b1 100644 --- a/DependencyInjection/HappyrAuth0Extension.php +++ b/DependencyInjection/HappyrAuth0Extension.php @@ -28,6 +28,12 @@ public function load(array $configs, ContainerBuilder $container) if ($config['security']) { $loader->load('security.yml'); + + $container->getDefinition('happyr.auth0.security.authentication.entry_point.oauth') + ->replaceArgument(4, $config['csrf_protection']); + + $container->getDefinition('happyr.auth0.security.authentication.listener.sso') + ->addMethodCall('setCsrfProtection', $config['csrf_protection']); } // Add the secret key as parameter diff --git a/Resources/config/security.yml b/Resources/config/security.yml index b733dc7..fb0ef1c 100644 --- a/Resources/config/security.yml +++ b/Resources/config/security.yml @@ -19,4 +19,5 @@ services: - "@security.http_utils" - "%auth0.client_id%" - "%auth0.domain%" + - ~ # CSRF Protection set by configuration abstract: true diff --git a/Security/EntryPoint/SSOEntryPoint.php b/Security/EntryPoint/SSOEntryPoint.php index 0a180bd..e15c195 100644 --- a/Security/EntryPoint/SSOEntryPoint.php +++ b/Security/EntryPoint/SSOEntryPoint.php @@ -39,18 +39,30 @@ class SSOEntryPoint implements AuthenticationEntryPointInterface */ private $callbackPath; + /** + * @var string + */ + private $csrfProtectionEnabled; + /** * @param HttpUtils $httpUtils * @param $auth0ClientId * @param string $auth0Domain */ - public function __construct(CsrfTokenManager $csrfTokenManager, HttpUtils $httpUtils, $auth0ClientId, $auth0Domain, $callbackPath) - { + public function __construct( + CsrfTokenManager $csrfTokenManager, + HttpUtils $httpUtils, + $auth0ClientId, + $auth0Domain, + $callbackPath, + $csrfProtectionEnabled = true + ) { $this->csrfTokenManager = $csrfTokenManager; $this->httpUtils = $httpUtils; $this->auth0ClientId = $auth0ClientId; $this->auth0Domain = $auth0Domain; $this->callbackPath = $callbackPath; + $this->csrfProtectionEnabled = $csrfProtectionEnabled; } /** @@ -58,16 +70,17 @@ public function __construct(CsrfTokenManager $csrfTokenManager, HttpUtils $httpU */ public function start(Request $request, AuthenticationException $authException = null) { - $csrfToken = $this->csrfTokenManager->getToken('auth0-sso'); - $query = [ 'client_id' => $this->auth0ClientId, 'redirect_uri' => $this->httpUtils->generateUri($request, $this->callbackPath), 'response_type' => 'code', 'language' => $request->getLocale(), - 'state' => $csrfToken->getValue(), ]; + if ($this->csrfProtectionEnabled) { + $query['state'] = $this->csrfTokenManager->getToken('auth0-sso')->getValue(); + } + return new RedirectResponse(sprintf('https://%s/authorize?%s', $this->auth0Domain, http_build_query($query))); } } diff --git a/Security/Firewall/SSOListener.php b/Security/Firewall/SSOListener.php index 505ceea..b2010f7 100644 --- a/Security/Firewall/SSOListener.php +++ b/Security/Firewall/SSOListener.php @@ -32,6 +32,11 @@ class SSOListener extends AbstractAuthenticationListener */ private $csrfTokenManager; + /** + * @var bool + */ + private $csrfProtectionEnabled = true; + public function setCsrfTokenManager(CsrfTokenManager $csrfTokenManager) { $this->csrfTokenManager = $csrfTokenManager; @@ -45,6 +50,11 @@ public function setAuthenticationApi($authenticationApi) $this->authenticationApi = $authenticationApi; } + public function setCsrfProtection($protectionEnabled = true) + { + $this->csrfProtectionEnabled = $protectionEnabled; + } + /** * @param string $callbackPath * @@ -63,12 +73,14 @@ protected function attemptAuthentication(Request $request) throw new AuthenticationException('No oauth code in the request.'); } - if (null === $state = $request->query->get('state')) { - throw new AuthenticationException('No state in the request.'); - } + if ($this->csrfProtectionEnabled) { + if (null === $state = $request->query->get('state')) { + throw new AuthenticationException('No state in the request.'); + } - if (!$this->csrfTokenManager->isTokenValid(new CsrfToken('auth0-sso', $state))) { - throw new AuthenticationException('Invalid CSRF token'); + if (!$this->csrfTokenManager->isTokenValid(new CsrfToken('auth0-sso', $state))) { + throw new AuthenticationException('Invalid CSRF token'); + } } $tokenStruct = $this->authenticationApi