diff --git a/Authentication/SimpleAuthenticationHandler.php b/Authentication/SimpleAuthenticationHandler.php index 86ac918e..1e210a6a 100644 --- a/Authentication/SimpleAuthenticationHandler.php +++ b/Authentication/SimpleAuthenticationHandler.php @@ -62,7 +62,7 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token) } if (null !== $response) { - throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationSuccess method must return null to use the default success handler, or a Response object', \get_class($this->simpleAuthenticator))); + throw new \UnexpectedValueException(sprintf('The "%s::onAuthenticationSuccess()" method must return null to use the default success handler, or a Response object.', \get_class($this->simpleAuthenticator))); } } @@ -89,7 +89,7 @@ public function onAuthenticationFailure(Request $request, AuthenticationExceptio } if (null !== $response) { - throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationFailure method must return null to use the default failure handler, or a Response object', \get_class($this->simpleAuthenticator))); + throw new \UnexpectedValueException(sprintf('The "%s::onAuthenticationFailure()" method must return null to use the default failure handler, or a Response object.', \get_class($this->simpleAuthenticator))); } } diff --git a/Firewall/AnonymousAuthenticationListener.php b/Firewall/AnonymousAuthenticationListener.php index 0f1da391..999796d3 100644 --- a/Firewall/AnonymousAuthenticationListener.php +++ b/Firewall/AnonymousAuthenticationListener.php @@ -19,6 +19,9 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; +// Help opcache.preload discover always-needed symbols +class_exists(AnonymousToken::class); + /** * AnonymousAuthenticationListener automatically adds a Token if none is * already present. diff --git a/Firewall/ContextListener.php b/Firewall/ContextListener.php index 9243119a..1201e161 100644 --- a/Firewall/ContextListener.php +++ b/Firewall/ContextListener.php @@ -115,10 +115,10 @@ public function authenticate(RequestEvent $event) if (null !== $session) { $usageIndexValue = method_exists(Request::class, 'getPreferredFormat') && $session instanceof Session ? $usageIndexReference = &$session->getUsageIndex() : 0; - $sessionId = $session->getId(); + $sessionId = $request->cookies->get($session->getName()); $token = $session->get($this->sessionKey); - if ($this->sessionTrackerEnabler && $session->getId() === $sessionId) { + if ($this->sessionTrackerEnabler && \in_array($sessionId, [true, $session->getId()], true)) { $usageIndexReference = $usageIndexValue; } } diff --git a/Firewall/ExceptionListener.php b/Firewall/ExceptionListener.php index 2f97c7e0..68cb6f31 100644 --- a/Firewall/ExceptionListener.php +++ b/Firewall/ExceptionListener.php @@ -216,7 +216,7 @@ private function startAuthentication(Request $request, AuthenticationException $ if (!$response instanceof Response) { $given = \is_object($response) ? \get_class($response) : \gettype($response); - throw new \LogicException(sprintf('The %s::start() method must return a Response object (%s returned)', \get_class($this->authenticationEntryPoint), $given)); + throw new \LogicException(sprintf('The "%s::start()" method must return a Response object ("%s" returned).', \get_class($this->authenticationEntryPoint), $given)); } return $response; diff --git a/Firewall/LegacyListenerTrait.php b/Firewall/LegacyListenerTrait.php index 260cb680..6f2bc223 100644 --- a/Firewall/LegacyListenerTrait.php +++ b/Firewall/LegacyListenerTrait.php @@ -15,6 +15,9 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\RequestEvent; +// Help opcache.preload discover always-needed symbols +class_exists(RequestEvent::class); + /** * @deprecated * diff --git a/Firewall/RemoteUserAuthenticationListener.php b/Firewall/RemoteUserAuthenticationListener.php index 592e0127..a33ed27f 100644 --- a/Firewall/RemoteUserAuthenticationListener.php +++ b/Firewall/RemoteUserAuthenticationListener.php @@ -41,7 +41,7 @@ public function __construct(TokenStorageInterface $tokenStorage, AuthenticationM protected function getPreAuthenticatedData(Request $request) { if (!$request->server->has($this->userKey)) { - throw new BadCredentialsException(sprintf('User key was not found: %s', $this->userKey)); + throw new BadCredentialsException(sprintf('User key was not found: "%s".', $this->userKey)); } return [$request->server->get($this->userKey), null]; diff --git a/Firewall/SimpleFormAuthenticationListener.php b/Firewall/SimpleFormAuthenticationListener.php index 3d1895f4..dc625879 100644 --- a/Firewall/SimpleFormAuthenticationListener.php +++ b/Firewall/SimpleFormAuthenticationListener.php @@ -47,7 +47,7 @@ class SimpleFormAuthenticationListener extends AbstractAuthenticationListener public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, string $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = [], LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfTokenManagerInterface $csrfTokenManager = null, SimpleFormAuthenticatorInterface $simpleAuthenticator = null) { if (!$simpleAuthenticator) { - throw new \InvalidArgumentException('Missing simple authenticator'); + throw new \InvalidArgumentException('Missing simple authenticator.'); } $this->simpleAuthenticator = $simpleAuthenticator; diff --git a/Firewall/SimplePreAuthenticationListener.php b/Firewall/SimplePreAuthenticationListener.php index bfbda2ba..daa9939c 100644 --- a/Firewall/SimplePreAuthenticationListener.php +++ b/Firewall/SimplePreAuthenticationListener.php @@ -146,7 +146,7 @@ public function authenticate(RequestEvent $event) if ($response instanceof Response) { $event->setResponse($response); } elseif (null !== $response) { - throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationFailure method must return null or a Response object', \get_class($this->simpleAuthenticator))); + throw new \UnexpectedValueException(sprintf('The "%s::onAuthenticationFailure()" method must return null or a Response object.', \get_class($this->simpleAuthenticator))); } } @@ -158,7 +158,7 @@ public function authenticate(RequestEvent $event) if ($response instanceof Response) { $event->setResponse($response); } elseif (null !== $response) { - throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationSuccess method must return null or a Response object', \get_class($this->simpleAuthenticator))); + throw new \UnexpectedValueException(sprintf('The "%s::onAuthenticationSuccess()" method must return null or a Response object.', \get_class($this->simpleAuthenticator))); } } } diff --git a/Firewall/X509AuthenticationListener.php b/Firewall/X509AuthenticationListener.php index 7e785bdb..c15c8ff7 100644 --- a/Firewall/X509AuthenticationListener.php +++ b/Firewall/X509AuthenticationListener.php @@ -52,7 +52,7 @@ protected function getPreAuthenticatedData(Request $request) } if (null === $user) { - throw new BadCredentialsException(sprintf('SSL credentials not found: %s, %s', $this->userKey, $this->credentialKey)); + throw new BadCredentialsException(sprintf('SSL credentials not found: "%s", "%s".', $this->userKey, $this->credentialKey)); } return [$user, $request->server->get($this->credentialKey, '')]; diff --git a/RememberMe/AbstractRememberMeServices.php b/RememberMe/AbstractRememberMeServices.php index 86919599..41d61732 100644 --- a/RememberMe/AbstractRememberMeServices.php +++ b/RememberMe/AbstractRememberMeServices.php @@ -39,6 +39,7 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface protected $options = [ 'secure' => false, 'httponly' => true, + 'samesite' => null, ]; private $providerKey; private $secret; @@ -260,7 +261,7 @@ protected function encodeCookie(array $cookieParts) { foreach ($cookieParts as $cookiePart) { if (false !== strpos($cookiePart, self::COOKIE_DELIMITER)) { - throw new \InvalidArgumentException(sprintf('$cookieParts should not contain the cookie delimiter "%s"', self::COOKIE_DELIMITER)); + throw new \InvalidArgumentException(sprintf('$cookieParts should not contain the cookie delimiter "%s".', self::COOKIE_DELIMITER)); } } @@ -276,7 +277,7 @@ protected function cancelCookie(Request $request) $this->logger->debug('Clearing remember-me cookie.', ['name' => $this->options['name']]); } - $request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie($this->options['name'], null, 1, $this->options['path'], $this->options['domain'], $this->options['secure'] ?? $request->isSecure(), $this->options['httponly'], false, $this->options['samesite'] ?? null)); + $request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie($this->options['name'], null, 1, $this->options['path'], $this->options['domain'], $this->options['secure'] ?? $request->isSecure(), $this->options['httponly'], false, $this->options['samesite'])); } /** diff --git a/RememberMe/PersistentTokenBasedRememberMeServices.php b/RememberMe/PersistentTokenBasedRememberMeServices.php index 61b1257b..167a0947 100644 --- a/RememberMe/PersistentTokenBasedRememberMeServices.php +++ b/RememberMe/PersistentTokenBasedRememberMeServices.php @@ -86,7 +86,7 @@ protected function processAutoLoginCookie(array $cookieParts, Request $request) $this->options['secure'] ?? $request->isSecure(), $this->options['httponly'], false, - $this->options['samesite'] ?? null + $this->options['samesite'] ) ); @@ -121,7 +121,7 @@ protected function onLoginSuccess(Request $request, Response $response, TokenInt $this->options['secure'] ?? $request->isSecure(), $this->options['httponly'], false, - $this->options['samesite'] ?? null + $this->options['samesite'] ) ); } diff --git a/RememberMe/TokenBasedRememberMeServices.php b/RememberMe/TokenBasedRememberMeServices.php index 6db2a783..8dfce95a 100644 --- a/RememberMe/TokenBasedRememberMeServices.php +++ b/RememberMe/TokenBasedRememberMeServices.php @@ -83,7 +83,7 @@ protected function onLoginSuccess(Request $request, Response $response, TokenInt $this->options['secure'] ?? $request->isSecure(), $this->options['httponly'], false, - $this->options['samesite'] ?? null + $this->options['samesite'] ) ); } diff --git a/Session/SessionAuthenticationStrategy.php b/Session/SessionAuthenticationStrategy.php index a20619af..cb788a8e 100644 --- a/Session/SessionAuthenticationStrategy.php +++ b/Session/SessionAuthenticationStrategy.php @@ -59,7 +59,7 @@ public function onAuthentication(Request $request, TokenInterface $token) return; default: - throw new \RuntimeException(sprintf('Invalid session authentication strategy "%s"', $this->strategy)); + throw new \RuntimeException(sprintf('Invalid session authentication strategy "%s".', $this->strategy)); } } } diff --git a/Tests/Authentication/SimpleAuthenticationHandlerTest.php b/Tests/Authentication/SimpleAuthenticationHandlerTest.php index 107a1337..9fbdd677 100644 --- a/Tests/Authentication/SimpleAuthenticationHandlerTest.php +++ b/Tests/Authentication/SimpleAuthenticationHandlerTest.php @@ -84,7 +84,7 @@ public function testOnAuthenticationSuccessCallsSimpleAuthenticator() public function testOnAuthenticationSuccessThrowsAnExceptionIfNonResponseIsReturned() { $this->expectException('UnexpectedValueException'); - $this->expectExceptionMessage('onAuthenticationSuccess method must return null to use the default success handler, or a Response object'); + $this->expectExceptionMessage('onAuthenticationSuccess()" method must return null to use the default success handler, or a Response object'); $this->successHandler->expects($this->never()) ->method('onAuthenticationSuccess'); @@ -152,7 +152,7 @@ public function testOnAuthenticationFailureCallsSimpleAuthenticator() public function testOnAuthenticationFailureThrowsAnExceptionIfNonResponseIsReturned() { $this->expectException('UnexpectedValueException'); - $this->expectExceptionMessage('onAuthenticationFailure method must return null to use the default failure handler, or a Response object'); + $this->expectExceptionMessage('onAuthenticationFailure()" method must return null to use the default failure handler, or a Response object'); $this->failureHandler->expects($this->never()) ->method('onAuthenticationFailure'); diff --git a/Tests/Firewall/ContextListenerTest.php b/Tests/Firewall/ContextListenerTest.php index 0d053190..82a5f917 100644 --- a/Tests/Firewall/ContextListenerTest.php +++ b/Tests/Firewall/ContextListenerTest.php @@ -344,6 +344,26 @@ public function testDeauthenticatedEvent() $this->assertNull($tokenStorage->getToken()); } + /** + * @requires function \Symfony\Component\HttpFoundation\Request::getPreferredFormat + */ + public function testWithPreviousNotStartedSession() + { + $session = new Session(new MockArraySessionStorage()); + + $request = new Request(); + $request->setSession($session); + $request->cookies->set('MOCKSESSID', true); + + $usageIndex = $session->getUsageIndex(); + + $tokenStorage = new TokenStorage(); + $listener = new ContextListener($tokenStorage, [], 'context_key', null, null, null, [$tokenStorage, 'getToken']); + $listener(new RequestEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, HttpKernelInterface::MASTER_REQUEST)); + + $this->assertSame($usageIndex, $session->getUsageIndex()); + } + protected function runSessionOnKernelResponse($newToken, $original = null) { $session = new Session(new MockArraySessionStorage()); diff --git a/Tests/Firewall/ExceptionListenerTest.php b/Tests/Firewall/ExceptionListenerTest.php index 2715c940..3713ec7b 100644 --- a/Tests/Firewall/ExceptionListenerTest.php +++ b/Tests/Firewall/ExceptionListenerTest.php @@ -83,7 +83,7 @@ public function testExceptionWhenEntryPointReturnsBadValue() $listener->onKernelException($event); // the exception has been replaced by our LogicException $this->assertInstanceOf('LogicException', $event->getThrowable()); - $this->assertStringEndsWith('start() method must return a Response object (string returned)', $event->getThrowable()->getMessage()); + $this->assertStringEndsWith('start()" method must return a Response object ("string" returned).', $event->getThrowable()->getMessage()); } /**