diff --git a/DependencyInjection/Security/Factory/Factory.php b/DependencyInjection/Security/Factory/Factory.php index 00fc5c4..4b1bae5 100644 --- a/DependencyInjection/Security/Factory/Factory.php +++ b/DependencyInjection/Security/Factory/Factory.php @@ -54,7 +54,8 @@ public function create(ContainerBuilder $container, $id, $config, $userProviderI ->replaceArgument(3, new Reference($this->encoderId)) ->replaceArgument(4, new Reference($this->nonceCacheId)) ->replaceArgument(5, $config['lifetime']) - ->replaceArgument(6, $config['date_format']); + ->replaceArgument(6, $config['date_format']) + ->replaceArgument(7, $config['clock_skew']); $entryPointId = $this->createEntryPoint($container, $id, $config, $defaultEntryPoint); @@ -99,7 +100,8 @@ public function addConfiguration(NodeDefinition $node) ->scalarNode('date_format')->defaultValue( '/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/' )->end() - ->arrayNode('encoder') + ->scalarNode('clock_skew')->defaultValue(0)->end() + ->arrayNode('encoder') ->children() ->scalarNode('algorithm')->end() ->scalarNode('encodeHashAsBase64')->end() diff --git a/Resources/config/services.yml b/Resources/config/services.yml index a3b4a66..c74ef26 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -1,7 +1,7 @@ services: escape_wsse_authentication.provider: class: '%escape_wsse_authentication.provider.class%' - arguments: ['@security.user_checker', null, null, null, null, 300, '/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/'] + arguments: ['@security.user_checker', null, null, null, null, 300, '/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/',0] escape_wsse_authentication.listener: class: '%escape_wsse_authentication.listener.class%' diff --git a/Security/Core/Authentication/Provider/Provider.php b/Security/Core/Authentication/Provider/Provider.php index 73d76b7..153a9c5 100644 --- a/Security/Core/Authentication/Provider/Provider.php +++ b/Security/Core/Authentication/Provider/Provider.php @@ -25,6 +25,7 @@ class Provider implements AuthenticationProviderInterface private $nonceCache; private $lifetime; private $dateFormat; + private $clockSkew; /** * Constructor. @@ -36,7 +37,8 @@ class Provider implements AuthenticationProviderInterface * @param Cache $nonceCache The nonce cache * @param int $lifetime The lifetime * @param string $dateFormat The date format - */ + * @param int $clockSkew The margin in seconds to mitigate clock skew + */ public function __construct( UserCheckerInterface $userChecker, UserProviderInterface $userProvider, @@ -44,7 +46,8 @@ public function __construct( PasswordEncoderInterface $encoder, Cache $nonceCache, $lifetime=300, - $dateFormat='/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/' + $dateFormat='/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/', + $clockSkew = 0 ) { if(empty($providerKey)) @@ -59,6 +62,7 @@ public function __construct( $this->nonceCache = $nonceCache; $this->lifetime = $lifetime; $this->dateFormat = $dateFormat; + $this->clockSkew = $clockSkew; } public function authenticate(TokenInterface $token) @@ -154,7 +158,7 @@ protected function getCurrentTime() protected function isTokenFromFuture($created) { - return strtotime($created) > strtotime($this->getCurrentTime()); + return strtotime($created) - $this->clockSkew > strtotime($this->getCurrentTime()); } protected function isFormattedCorrectly($created) diff --git a/Tests/DependencyInjection/Security/Factory/FactoryTest.php b/Tests/DependencyInjection/Security/Factory/FactoryTest.php index d7e73c3..a63adf3 100644 --- a/Tests/DependencyInjection/Security/Factory/FactoryTest.php +++ b/Tests/DependencyInjection/Security/Factory/FactoryTest.php @@ -46,6 +46,7 @@ public function testCreate() $profile = 'someprofile'; $lifetime = 300; $date_format = '/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/'; + $clock_skew = 0; $algorithm = 'sha1'; $encodeHashAsBase64 = true; @@ -68,7 +69,8 @@ public function testCreate() 'profile' => $profile, 'encoder' => $encoder, 'lifetime' => $lifetime, - 'date_format' => $date_format + 'date_format' => $date_format, + 'clock_skew' => $clock_skew ), 'user_provider', 'entry_point' @@ -108,7 +110,8 @@ public function testCreate() 'index_3' => new Reference($encoderId), 'index_4' => new Reference($nonceCacheId), 'index_5' => $lifetime, - 'index_6' => $date_format + 'index_6' => $date_format, + 'index_7' => $clock_skew ), $definition->getArguments() );