diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/GuardedBundle/AppCustomAuthenticator.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/GuardedBundle/AppCustomAuthenticator.php index fef2732759fa..22d378835e4c 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/GuardedBundle/AppCustomAuthenticator.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/GuardedBundle/AppCustomAuthenticator.php @@ -23,7 +23,7 @@ class AppCustomAuthenticator extends AbstractGuardAuthenticator { public function supports(Request $request) { - return true; + return '/manual_login' !== $request->getPathInfo() && '/profile' !== $request->getPathInfo(); } public function getCredentials(Request $request) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/GuardedBundle/AuthenticationController.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/GuardedBundle/AuthenticationController.php new file mode 100644 index 000000000000..9833d0551383 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/GuardedBundle/AuthenticationController.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Core\User\User; +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Guard\GuardAuthenticatorHandler; +use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; + +class AuthenticationController +{ + public function manualLoginAction(GuardAuthenticatorHandler $guardAuthenticatorHandler, Request $request) + { + $guardAuthenticatorHandler->authenticateWithToken(new PostAuthenticationGuardToken(new User('Jane', 'test', ['ROLE_USER']), 'secure', ['ROLE_USER']), $request, 'secure'); + + return new Response('Logged in.'); + } + + public function profileAction(UserInterface $user = null) + { + if (null === $user) { + return new Response('Not logged in.'); + } + + return new Response('Username: '.$user->getUsername()); + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/GuardedTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/GuardedTest.php index bb0969c36a2f..83cd4118d76e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/GuardedTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/GuardedTest.php @@ -21,4 +21,14 @@ public function testGuarded() $this->assertSame(418, $client->getResponse()->getStatusCode()); } + + public function testManualLogin() + { + $client = $this->createClient(['debug' => true, 'test_case' => 'Guarded', 'root_config' => 'config.yml']); + + $client->request('GET', '/manual_login'); + $client->request('GET', '/profile'); + + $this->assertSame('Username: Jane', $client->getResponse()->getContent()); + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Guarded/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Guarded/config.yml index 2d1f779a530e..7f87c307d28b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Guarded/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Guarded/config.yml @@ -10,8 +10,19 @@ framework: services: logger: { class: Psr\Log\NullLogger } Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle\AppCustomAuthenticator: ~ + Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle\AuthenticationController: + tags: [controller.service_arguments] security: + encoders: + Symfony\Component\Security\Core\User\User: plaintext + + providers: + in_memory: + memory: + users: + Jane: { password: test, roles: [ROLE_USER] } + firewalls: secure: pattern: ^/ diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Guarded/routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Guarded/routing.yml index 4d1115437521..146aa811a143 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Guarded/routing.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Guarded/routing.yml @@ -3,3 +3,12 @@ main: defaults: _controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction path: /app +profile: + path: /profile + defaults: + _controller: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle\AuthenticationController::profileAction + +manual_login: + path: /manual_login + defaults: + _controller: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle\AuthenticationController::manualLoginAction diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php index bf491797aa25..dd8a5ae00420 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php @@ -49,6 +49,11 @@ public function setToken(TokenInterface $token = null) @trigger_error(sprintf('Not implementing the "%s::getRoleNames()" method in "%s" is deprecated since Symfony 4.3.', TokenInterface::class, \get_class($token)), E_USER_DEPRECATED); } + if ($token) { + // ensure any initializer is called + $this->getToken(); + } + $this->initializer = null; $this->token = $token; } diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/UsageTrackingTokenStorage.php b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/UsageTrackingTokenStorage.php index 3ce8913aa4fb..b90d5ab28b63 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/UsageTrackingTokenStorage.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/UsageTrackingTokenStorage.php @@ -52,6 +52,11 @@ public function getToken(): ?TokenInterface public function setToken(TokenInterface $token = null): void { $this->storage->setToken($token); + + if ($token && $this->enableUsageTracking) { + // increments the internal session usage index + $this->sessionLocator->get('session')->getMetadataBag(); + } } public function enableUsageTracking(): void diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index 82a5f917d98e..7e89c0b1b36f 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -411,9 +411,9 @@ protected function runSessionOnKernelResponse($newToken, $original = null) private function handleEventWithPreviousSession($userProviders, UserInterface $user = null, RememberMeServicesInterface $rememberMeServices = null) { - $user = $user ?: new User('foo', 'bar'); + $tokenUser = $user ?: new User('foo', 'bar'); $session = new Session(new MockArraySessionStorage()); - $session->set('_security_context_key', serialize(new UsernamePasswordToken($user, '', 'context_key', ['ROLE_USER']))); + $session->set('_security_context_key', serialize(new UsernamePasswordToken($tokenUser, '', 'context_key', ['ROLE_USER']))); $request = new Request(); $request->setSession($session); @@ -442,6 +442,10 @@ private function handleEventWithPreviousSession($userProviders, UserInterface $u $listener(new RequestEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, HttpKernelInterface::MASTER_REQUEST)); if (null !== $usageIndex) { + if (null !== $user) { + ++$usageIndex; + } + $this->assertSame($usageIndex, $session->getUsageIndex()); $tokenStorage->getToken(); $this->assertSame(1 + $usageIndex, $session->getUsageIndex()); diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index 699ffcf7032b..6b23f5cc8e31 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^7.1.3", - "symfony/security-core": "^4.4.7", + "symfony/security-core": "^4.4.8", "symfony/http-foundation": "^3.4.40|^4.4.7|^5.0.7", "symfony/http-kernel": "^4.4", "symfony/property-access": "^3.4|^4.0|^5.0"