/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php

http://github.com/symfony/symfony · PHP · 355 lines · 285 code · 62 blank · 8 comment · 3 complexity · 73ca20d024aa8b1a584421a9b76b14ce MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider;
  13. use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;
  14. use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
  15. use Symfony\Component\Security\Core\Tests\Encoder\TestPasswordEncoderInterface;
  16. use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
  17. use Symfony\Component\Security\Core\User\User;
  18. use Symfony\Component\Security\Core\User\UserInterface;
  19. use Symfony\Component\Security\Core\User\UserProviderInterface;
  20. class DaoAuthenticationProviderTest extends TestCase
  21. {
  22. public function testRetrieveUserWhenProviderDoesNotReturnAnUserInterface()
  23. {
  24. $this->expectException('Symfony\Component\Security\Core\Exception\AuthenticationServiceException');
  25. $provider = $this->getProvider('fabien');
  26. $method = new \ReflectionMethod($provider, 'retrieveUser');
  27. $method->setAccessible(true);
  28. $method->invoke($provider, 'fabien', $this->getSupportedToken());
  29. }
  30. public function testRetrieveUserWhenUsernameIsNotFound()
  31. {
  32. $this->expectException('Symfony\Component\Security\Core\Exception\UsernameNotFoundException');
  33. $userProvider = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface')->getMock();
  34. $userProvider->expects($this->once())
  35. ->method('loadUserByUsername')
  36. ->willThrowException(new UsernameNotFoundException())
  37. ;
  38. $provider = new DaoAuthenticationProvider($userProvider, $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface')->getMock(), 'key', $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface')->getMock());
  39. $method = new \ReflectionMethod($provider, 'retrieveUser');
  40. $method->setAccessible(true);
  41. $method->invoke($provider, 'fabien', $this->getSupportedToken());
  42. }
  43. public function testRetrieveUserWhenAnExceptionOccurs()
  44. {
  45. $this->expectException('Symfony\Component\Security\Core\Exception\AuthenticationServiceException');
  46. $userProvider = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface')->getMock();
  47. $userProvider->expects($this->once())
  48. ->method('loadUserByUsername')
  49. ->willThrowException(new \RuntimeException())
  50. ;
  51. $provider = new DaoAuthenticationProvider($userProvider, $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface')->getMock(), 'key', $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface')->getMock());
  52. $method = new \ReflectionMethod($provider, 'retrieveUser');
  53. $method->setAccessible(true);
  54. $method->invoke($provider, 'fabien', $this->getSupportedToken());
  55. }
  56. public function testRetrieveUserReturnsUserFromTokenOnReauthentication()
  57. {
  58. $userProvider = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface')->getMock();
  59. $userProvider->expects($this->never())
  60. ->method('loadUserByUsername')
  61. ;
  62. $user = new TestUser();
  63. $token = $this->getSupportedToken();
  64. $token->expects($this->once())
  65. ->method('getUser')
  66. ->willReturn($user)
  67. ;
  68. $provider = new DaoAuthenticationProvider($userProvider, $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface')->getMock(), 'key', $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface')->getMock());
  69. $reflection = new \ReflectionMethod($provider, 'retrieveUser');
  70. $reflection->setAccessible(true);
  71. $result = $reflection->invoke($provider, 'someUser', $token);
  72. $this->assertSame($user, $result);
  73. }
  74. public function testRetrieveUser()
  75. {
  76. $user = new TestUser();
  77. $userProvider = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface')->getMock();
  78. $userProvider->expects($this->once())
  79. ->method('loadUserByUsername')
  80. ->willReturn($user)
  81. ;
  82. $provider = new DaoAuthenticationProvider($userProvider, $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface')->getMock(), 'key', $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface')->getMock());
  83. $method = new \ReflectionMethod($provider, 'retrieveUser');
  84. $method->setAccessible(true);
  85. $this->assertSame($user, $method->invoke($provider, 'fabien', $this->getSupportedToken()));
  86. }
  87. public function testCheckAuthenticationWhenCredentialsAreEmpty()
  88. {
  89. $this->expectException('Symfony\Component\Security\Core\Exception\BadCredentialsException');
  90. $encoder = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface')->getMock();
  91. $encoder
  92. ->expects($this->never())
  93. ->method('isPasswordValid')
  94. ;
  95. $provider = $this->getProvider(null, null, $encoder);
  96. $method = new \ReflectionMethod($provider, 'checkAuthentication');
  97. $method->setAccessible(true);
  98. $token = $this->getSupportedToken();
  99. $token
  100. ->expects($this->once())
  101. ->method('getCredentials')
  102. ->willReturn('')
  103. ;
  104. $method->invoke($provider, new TestUser(), $token);
  105. }
  106. public function testCheckAuthenticationWhenCredentialsAre0()
  107. {
  108. $encoder = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface')->getMock();
  109. $encoder
  110. ->expects($this->once())
  111. ->method('isPasswordValid')
  112. ->willReturn(true)
  113. ;
  114. $provider = $this->getProvider(null, null, $encoder);
  115. $method = new \ReflectionMethod($provider, 'checkAuthentication');
  116. $method->setAccessible(true);
  117. $token = $this->getSupportedToken();
  118. $token
  119. ->expects($this->once())
  120. ->method('getCredentials')
  121. ->willReturn('0')
  122. ;
  123. $method->invoke(
  124. $provider,
  125. new User('username', 'password'),
  126. $token
  127. );
  128. }
  129. public function testCheckAuthenticationWhenCredentialsAreNotValid()
  130. {
  131. $this->expectException('Symfony\Component\Security\Core\Exception\BadCredentialsException');
  132. $encoder = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface')->getMock();
  133. $encoder->expects($this->once())
  134. ->method('isPasswordValid')
  135. ->willReturn(false)
  136. ;
  137. $provider = $this->getProvider(null, null, $encoder);
  138. $method = new \ReflectionMethod($provider, 'checkAuthentication');
  139. $method->setAccessible(true);
  140. $token = $this->getSupportedToken();
  141. $token->expects($this->once())
  142. ->method('getCredentials')
  143. ->willReturn('foo')
  144. ;
  145. $method->invoke($provider, new User('username', 'password'), $token);
  146. }
  147. public function testCheckAuthenticationDoesNotReauthenticateWhenPasswordHasChanged()
  148. {
  149. $this->expectException('Symfony\Component\Security\Core\Exception\BadCredentialsException');
  150. $user = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserInterface')->getMock();
  151. $user->expects($this->once())
  152. ->method('getPassword')
  153. ->willReturn('foo')
  154. ;
  155. $token = $this->getSupportedToken();
  156. $token->expects($this->once())
  157. ->method('getUser')
  158. ->willReturn($user);
  159. $dbUser = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserInterface')->getMock();
  160. $dbUser->expects($this->once())
  161. ->method('getPassword')
  162. ->willReturn('newFoo')
  163. ;
  164. $provider = $this->getProvider();
  165. $reflection = new \ReflectionMethod($provider, 'checkAuthentication');
  166. $reflection->setAccessible(true);
  167. $reflection->invoke($provider, $dbUser, $token);
  168. }
  169. public function testCheckAuthenticationWhenTokenNeedsReauthenticationWorksWithoutOriginalCredentials()
  170. {
  171. $user = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserInterface')->getMock();
  172. $user->expects($this->once())
  173. ->method('getPassword')
  174. ->willReturn('foo')
  175. ;
  176. $token = $this->getSupportedToken();
  177. $token->expects($this->once())
  178. ->method('getUser')
  179. ->willReturn($user);
  180. $dbUser = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserInterface')->getMock();
  181. $dbUser->expects($this->once())
  182. ->method('getPassword')
  183. ->willReturn('foo')
  184. ;
  185. $provider = $this->getProvider();
  186. $reflection = new \ReflectionMethod($provider, 'checkAuthentication');
  187. $reflection->setAccessible(true);
  188. $reflection->invoke($provider, $dbUser, $token);
  189. }
  190. public function testCheckAuthentication()
  191. {
  192. $encoder = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface')->getMock();
  193. $encoder->expects($this->once())
  194. ->method('isPasswordValid')
  195. ->willReturn(true)
  196. ;
  197. $provider = $this->getProvider(null, null, $encoder);
  198. $method = new \ReflectionMethod($provider, 'checkAuthentication');
  199. $method->setAccessible(true);
  200. $token = $this->getSupportedToken();
  201. $token->expects($this->once())
  202. ->method('getCredentials')
  203. ->willReturn('foo')
  204. ;
  205. $method->invoke($provider, new User('username', 'password'), $token);
  206. }
  207. public function testPasswordUpgrades()
  208. {
  209. $user = new User('user', 'pwd');
  210. $encoder = $this->getMockBuilder(TestPasswordEncoderInterface::class)->getMock();
  211. $encoder->expects($this->once())
  212. ->method('isPasswordValid')
  213. ->willReturn(true)
  214. ;
  215. $encoder->expects($this->once())
  216. ->method('encodePassword')
  217. ->willReturn('foobar')
  218. ;
  219. $encoder->expects($this->once())
  220. ->method('needsRehash')
  221. ->willReturn(true)
  222. ;
  223. $provider = $this->getProvider(null, null, $encoder);
  224. $userProvider = ((array) $provider)[sprintf("\0%s\0userProvider", DaoAuthenticationProvider::class)];
  225. $userProvider->expects($this->once())
  226. ->method('upgradePassword')
  227. ->with($user, 'foobar')
  228. ;
  229. $method = new \ReflectionMethod($provider, 'checkAuthentication');
  230. $method->setAccessible(true);
  231. $token = $this->getSupportedToken();
  232. $token->expects($this->once())
  233. ->method('getCredentials')
  234. ->willReturn('foo')
  235. ;
  236. $method->invoke($provider, $user, $token);
  237. }
  238. protected function getSupportedToken()
  239. {
  240. $mock = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken')->setMethods(['getCredentials', 'getUser', 'getProviderKey'])->disableOriginalConstructor()->getMock();
  241. $mock
  242. ->expects($this->any())
  243. ->method('getProviderKey')
  244. ->willReturn('key')
  245. ;
  246. return $mock;
  247. }
  248. protected function getProvider($user = null, $userChecker = null, $passwordEncoder = null)
  249. {
  250. $userProvider = $this->getMockBuilder([UserProviderInterface::class, PasswordUpgraderInterface::class])->getMock();
  251. if (null !== $user) {
  252. $userProvider->expects($this->once())
  253. ->method('loadUserByUsername')
  254. ->willReturn($user)
  255. ;
  256. }
  257. if (null === $userChecker) {
  258. $userChecker = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface')->getMock();
  259. }
  260. if (null === $passwordEncoder) {
  261. $passwordEncoder = new PlaintextPasswordEncoder();
  262. }
  263. $encoderFactory = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface')->getMock();
  264. $encoderFactory
  265. ->expects($this->any())
  266. ->method('getEncoder')
  267. ->willReturn($passwordEncoder)
  268. ;
  269. return new DaoAuthenticationProvider($userProvider, $userChecker, 'key', $encoderFactory);
  270. }
  271. }
  272. class TestUser implements UserInterface
  273. {
  274. public function getRoles(): array
  275. {
  276. return [];
  277. }
  278. public function getPassword(): ?string
  279. {
  280. return 'secret';
  281. }
  282. public function getSalt(): ?string
  283. {
  284. return null;
  285. }
  286. public function getUsername(): string
  287. {
  288. return 'jane_doe';
  289. }
  290. public function eraseCredentials()
  291. {
  292. }
  293. }