Skip to content

Commit 8e92dfa

Browse files
committed
Add support for the new remember-me system for the programmatic login
1 parent b8386cb commit 8e92dfa

File tree

3 files changed

+72
-42
lines changed

3 files changed

+72
-42
lines changed

DependencyInjection/Compiler/InjectRememberMeServicesPass.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ public function process(ContainerBuilder $container)
3434
$firewallName = $container->getParameter('fos_user.firewall_name');
3535
$loginManager = $container->getDefinition('fos_user.security.login_manager');
3636

37-
if ($container->hasDefinition('security.authentication.rememberme.services.persistent.'.$firewallName)) {
37+
if ($container->has('security.authenticator.remember_me_handler.'.$firewallName)) {
38+
$loginManager->replaceArgument(4, new Reference('security.authenticator.remember_me_handler.'.$firewallName));
39+
} elseif ($container->hasDefinition('security.authentication.rememberme.services.persistent.'.$firewallName)) {
3840
$loginManager->replaceArgument(4, new Reference('security.authentication.rememberme.services.persistent.'.$firewallName));
3941
} elseif ($container->hasDefinition('security.authentication.rememberme.services.simplehash.'.$firewallName)) {
4042
$loginManager->replaceArgument(4, new Reference('security.authentication.rememberme.services.simplehash.'.$firewallName));

Security/LoginManager.php

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
1818
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
1919
use Symfony\Component\Security\Core\User\UserCheckerInterface;
20+
use Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;
2021
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
2122
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
2223

@@ -48,23 +49,27 @@ class LoginManager implements LoginManagerInterface
4849
private $requestStack;
4950

5051
/**
51-
* @var RememberMeServicesInterface
52+
* @var RememberMeHandlerInterface|RememberMeServicesInterface|null
5253
*/
53-
private $rememberMeService;
54+
private $rememberMeHandler;
5455

5556
/**
56-
* LoginManager constructor.
57+
* @param RememberMeHandlerInterface|RememberMeServicesInterface|null $rememberMeHandler
5758
*/
5859
public function __construct(TokenStorageInterface $tokenStorage, UserCheckerInterface $userChecker,
5960
SessionAuthenticationStrategyInterface $sessionStrategy,
6061
RequestStack $requestStack,
61-
RememberMeServicesInterface $rememberMeService = null
62+
$rememberMeHandler = null
6263
) {
64+
if (null !== $rememberMeHandler && !$rememberMeHandler instanceof RememberMeHandlerInterface && !$rememberMeHandler instanceof RememberMeServicesInterface) {
65+
throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be an instance of "%s|%s|null", "%s" given.', __METHOD__, RememberMeHandlerInterface::class, RememberMeServicesInterface::class, \is_object($rememberMeHandler) ? \get_class($rememberMeHandler) : \gettype($rememberMeHandler)));
66+
}
67+
6368
$this->tokenStorage = $tokenStorage;
6469
$this->userChecker = $userChecker;
6570
$this->sessionStrategy = $sessionStrategy;
6671
$this->requestStack = $requestStack;
67-
$this->rememberMeService = $rememberMeService;
72+
$this->rememberMeHandler = $rememberMeHandler;
6873
}
6974

7075
/**
@@ -80,8 +85,10 @@ final public function logInUser($firewallName, UserInterface $user, Response $re
8085
if (null !== $request) {
8186
$this->sessionStrategy->onAuthentication($request, $token);
8287

83-
if (null !== $response && null !== $this->rememberMeService) {
84-
$this->rememberMeService->loginSuccess($request, $response, $token);
88+
if (null !== $response && $this->rememberMeHandler instanceof RememberMeServicesInterface) {
89+
$this->rememberMeHandler->loginSuccess($request, $response, $token);
90+
} elseif ($this->rememberMeHandler instanceof RememberMeHandlerInterface) {
91+
$this->rememberMeHandler->createRememberMeCookie($user);
8592
}
8693
}
8794

Tests/Security/LoginManagerTest.php

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,17 @@
1111

1212
namespace FOS\UserBundle\Tests\Security;
1313

14+
use FOS\UserBundle\Model\UserInterface;
1415
use FOS\UserBundle\Security\LoginManager;
1516
use PHPUnit\Framework\TestCase;
17+
use Symfony\Component\HttpFoundation\Request;
18+
use Symfony\Component\HttpFoundation\RequestStack;
1619
use Symfony\Component\HttpFoundation\Response;
20+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
21+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
22+
use Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;
23+
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
24+
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
1725

1826
class LoginManagerTest extends TestCase
1927
{
@@ -23,66 +31,79 @@ public function testLogInUserWithRequestStack()
2331
$loginManager->logInUser('main', $this->mockUser());
2432
}
2533

26-
public function testLogInUserWithRememberMeAndRequestStack()
34+
public function testLogInUserWithRememberMeHandler()
2735
{
28-
$response = $this->getMockBuilder('Symfony\Component\HttpFoundation\Response')->getMock();
36+
if (!interface_exists(RememberMeHandlerInterface::class)) {
37+
$this->markTestSkipped('This test requires Symfony 5.3+.');
38+
}
2939

30-
$loginManager = $this->createLoginManager('main', $response);
31-
$loginManager->logInUser('main', $this->mockUser(), $response);
40+
$response = new Response();
41+
$user = $this->mockUser();
42+
43+
$rememberMeHandler = $this->createMock(RememberMeHandlerInterface::class);
44+
$rememberMeHandler->expects($this->once())
45+
->method('createRememberMeCookie')
46+
->with($user);
47+
48+
$loginManager = $this->createLoginManager('main', $rememberMeHandler);
49+
$loginManager->logInUser('main', $user, $response);
3250
}
3351

3452
/**
35-
* @param string $firewallName
36-
*
37-
* @return LoginManager
53+
* @group legacy
3854
*/
39-
private function createLoginManager($firewallName, Response $response = null)
55+
public function testLogInUserWithRememberMeService()
4056
{
41-
$tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
57+
if (!interface_exists(RememberMeServicesInterface::class)) {
58+
$this->markTestSkipped('This test does not support Symfony 6+.');
59+
}
60+
61+
$response = new Response();
62+
63+
$rememberMeService = $this->createMock(RememberMeServicesInterface::class);
64+
$rememberMeService
65+
->expects($this->once())
66+
->method('loginSuccess')
67+
->with($this->isInstanceOf(Request::class), $response, $this->isInstanceOf(TokenInterface::class));
68+
69+
$loginManager = $this->createLoginManager('main', $rememberMeService);
70+
$loginManager->logInUser('main', $this->mockUser(), $response);
71+
}
4272

73+
/**
74+
* @param RememberMeHandlerInterface|RememberMeServicesInterface|null $rememberMeHandler
75+
*/
76+
private function createLoginManager(string $firewallName, $rememberMeHandler = null): LoginManager
77+
{
78+
$tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock();
4379
$tokenStorage
4480
->expects($this->once())
4581
->method('setToken')
46-
->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
82+
->with($this->isInstanceOf(TokenInterface::class));
4783

4884
$userChecker = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserCheckerInterface')->getMock();
4985
$userChecker
5086
->expects($this->once())
5187
->method('checkPreAuth')
52-
->with($this->isInstanceOf('FOS\UserBundle\Model\UserInterface'));
88+
->with($this->isInstanceOf(UserInterface::class));
5389

54-
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock();
90+
$request = new Request();
5591

56-
$sessionStrategy = $this->getMockBuilder('Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface')->getMock();
92+
$sessionStrategy = $this->getMockBuilder(SessionAuthenticationStrategyInterface::class)->getMock();
5793
$sessionStrategy
5894
->expects($this->once())
5995
->method('onAuthentication')
60-
->with($request, $this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
96+
->with($request, $this->isInstanceOf(TokenInterface::class));
6197

62-
$requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock();
63-
$requestStack
64-
->expects($this->once())
65-
->method('getCurrentRequest')
66-
->will($this->returnValue($request));
67-
68-
$rememberMe = null;
69-
if (null !== $response) {
70-
$rememberMe = $this->getMockBuilder('Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface')->getMock();
71-
$rememberMe
72-
->expects($this->once())
73-
->method('loginSuccess')
74-
->with($request, $response, $this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
75-
}
98+
$requestStack = new RequestStack();
99+
$requestStack->push($request);
76100

77-
return new LoginManager($tokenStorage, $userChecker, $sessionStrategy, $requestStack, $rememberMe);
101+
return new LoginManager($tokenStorage, $userChecker, $sessionStrategy, $requestStack, $rememberMeHandler);
78102
}
79103

80-
/**
81-
* @return mixed
82-
*/
83-
private function mockUser()
104+
private function mockUser(): UserInterface
84105
{
85-
$user = $this->getMockBuilder('FOS\UserBundle\Model\UserInterface')->getMock();
106+
$user = $this->getMockBuilder(UserInterface::class)->getMock();
86107
$user
87108
->expects($this->once())
88109
->method('getRoles')

0 commit comments

Comments
 (0)