PageRenderTime 26ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.php

https://github.com/jdewit/symfony
PHP | 329 lines | 265 code | 56 blank | 8 comment | 2 complexity | 00f4a5912cdf1f5487002bccdb8beb5d 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\Http\Tests\RememberMe;
  11. use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
  12. use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
  13. use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
  14. use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpFoundation\Response;
  17. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  18. use Symfony\Component\Security\Http\RememberMe\PersistentTokenBasedRememberMeServices;
  19. use Symfony\Component\Security\Core\Exception\TokenNotFoundException;
  20. use Symfony\Component\Security\Core\Exception\CookieTheftException;
  21. use Symfony\Component\Security\Core\Util\SecureRandom;
  22. class PersistentTokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase
  23. {
  24. public function testAutoLoginReturnsNullWhenNoCookie()
  25. {
  26. $service = $this->getService(null, array('name' => 'foo'));
  27. $this->assertNull($service->autoLogin(new Request()));
  28. }
  29. public function testAutoLoginThrowsExceptionOnInvalidCookie()
  30. {
  31. $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => false, 'remember_me_parameter' => 'foo'));
  32. $request = new Request;
  33. $request->request->set('foo', 'true');
  34. $request->cookies->set('foo', 'foo');
  35. $this->assertNull($service->autoLogin($request));
  36. $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
  37. }
  38. public function testAutoLoginThrowsExceptionOnNonExistentToken()
  39. {
  40. $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => false, 'remember_me_parameter' => 'foo'));
  41. $request = new Request;
  42. $request->request->set('foo', 'true');
  43. $request->cookies->set('foo', $this->encodeCookie(array(
  44. $series = 'fooseries',
  45. $tokenValue = 'foovalue',
  46. )));
  47. $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
  48. $tokenProvider
  49. ->expects($this->once())
  50. ->method('loadTokenBySeries')
  51. ->will($this->throwException(new TokenNotFoundException('Token not found.')))
  52. ;
  53. $service->setTokenProvider($tokenProvider);
  54. $this->assertNull($service->autoLogin($request));
  55. $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
  56. }
  57. public function testAutoLoginReturnsNullOnNonExistentUser()
  58. {
  59. $userProvider = $this->getProvider();
  60. $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600, 'secure' => false, 'httponly' => false));
  61. $request = new Request;
  62. $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));
  63. $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
  64. $tokenProvider
  65. ->expects($this->once())
  66. ->method('loadTokenBySeries')
  67. ->will($this->returnValue(new PersistentToken('fooclass', 'fooname', 'fooseries', 'foovalue', new \DateTime())))
  68. ;
  69. $service->setTokenProvider($tokenProvider);
  70. $userProvider
  71. ->expects($this->once())
  72. ->method('loadUserByUsername')
  73. ->will($this->throwException(new UsernameNotFoundException('user not found')))
  74. ;
  75. $this->assertNull($service->autoLogin($request));
  76. $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME));
  77. }
  78. public function testAutoLoginThrowsExceptionOnStolenCookieAndRemovesItFromThePersistentBackend()
  79. {
  80. $userProvider = $this->getProvider();
  81. $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true));
  82. $request = new Request;
  83. $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));
  84. $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
  85. $service->setTokenProvider($tokenProvider);
  86. $tokenProvider
  87. ->expects($this->once())
  88. ->method('loadTokenBySeries')
  89. ->will($this->returnValue(new PersistentToken('fooclass', 'foouser', 'fooseries', 'anotherFooValue', new \DateTime())))
  90. ;
  91. $tokenProvider
  92. ->expects($this->once())
  93. ->method('deleteTokenBySeries')
  94. ->with($this->equalTo('fooseries'))
  95. ->will($this->returnValue(null))
  96. ;
  97. try {
  98. $service->autoLogin($request);
  99. $this->fail('Expected CookieTheftException was not thrown.');
  100. } catch (CookieTheftException $theft) { }
  101. $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME));
  102. }
  103. public function testAutoLoginDoesNotAcceptAnExpiredCookie()
  104. {
  105. $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600));
  106. $request = new Request;
  107. $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));
  108. $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
  109. $tokenProvider
  110. ->expects($this->once())
  111. ->method('loadTokenBySeries')
  112. ->with($this->equalTo('fooseries'))
  113. ->will($this->returnValue(new PersistentToken('fooclass', 'username', 'fooseries', 'foovalue', new \DateTime('yesterday'))))
  114. ;
  115. $service->setTokenProvider($tokenProvider);
  116. $this->assertNull($service->autoLogin($request));
  117. $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME));
  118. }
  119. public function testAutoLogin()
  120. {
  121. $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
  122. $user
  123. ->expects($this->once())
  124. ->method('getRoles')
  125. ->will($this->returnValue(array('ROLE_FOO')))
  126. ;
  127. $userProvider = $this->getProvider();
  128. $userProvider
  129. ->expects($this->once())
  130. ->method('loadUserByUsername')
  131. ->with($this->equalTo('foouser'))
  132. ->will($this->returnValue($user))
  133. ;
  134. $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'secure' => false, 'httponly' => false, 'always_remember_me' => true, 'lifetime' => 3600));
  135. $request = new Request;
  136. $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));
  137. $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
  138. $tokenProvider
  139. ->expects($this->once())
  140. ->method('loadTokenBySeries')
  141. ->with($this->equalTo('fooseries'))
  142. ->will($this->returnValue(new PersistentToken('fooclass', 'foouser', 'fooseries', 'foovalue', new \DateTime())))
  143. ;
  144. $service->setTokenProvider($tokenProvider);
  145. $returnedToken = $service->autoLogin($request);
  146. $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', $returnedToken);
  147. $this->assertSame($user, $returnedToken->getUser());
  148. $this->assertEquals('fookey', $returnedToken->getKey());
  149. $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME));
  150. }
  151. public function testLogout()
  152. {
  153. $service = $this->getService(null, array('name' => 'foo', 'path' => '/foo', 'domain' => 'foodomain.foo'));
  154. $request = new Request();
  155. $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));
  156. $response = new Response();
  157. $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
  158. $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
  159. $tokenProvider
  160. ->expects($this->once())
  161. ->method('deleteTokenBySeries')
  162. ->with($this->equalTo('fooseries'))
  163. ->will($this->returnValue(null))
  164. ;
  165. $service->setTokenProvider($tokenProvider);
  166. $service->logout($request, $response, $token);
  167. $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME);
  168. $this->assertTrue($cookie->isCleared());
  169. $this->assertEquals('/foo', $cookie->getPath());
  170. $this->assertEquals('foodomain.foo', $cookie->getDomain());
  171. }
  172. public function testLogoutSimplyIgnoresNonSetRequestCookie()
  173. {
  174. $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
  175. $request = new Request;
  176. $response = new Response;
  177. $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
  178. $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
  179. $tokenProvider
  180. ->expects($this->never())
  181. ->method('deleteTokenBySeries')
  182. ;
  183. $service->setTokenProvider($tokenProvider);
  184. $service->logout($request, $response, $token);
  185. $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME);
  186. $this->assertTrue($cookie->isCleared());
  187. $this->assertEquals('/', $cookie->getPath());
  188. $this->assertNull($cookie->getDomain());
  189. }
  190. public function testLogoutSimplyIgnoresInvalidCookie()
  191. {
  192. $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
  193. $request = new Request;
  194. $request->cookies->set('foo', 'somefoovalue');
  195. $response = new Response;
  196. $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
  197. $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
  198. $tokenProvider
  199. ->expects($this->never())
  200. ->method('deleteTokenBySeries')
  201. ;
  202. $service->setTokenProvider($tokenProvider);
  203. $service->logout($request, $response, $token);
  204. $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
  205. }
  206. public function testLoginFail()
  207. {
  208. $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
  209. $request = new Request();
  210. $this->assertFalse($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME));
  211. $service->loginFail($request);
  212. $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
  213. }
  214. public function testLoginSuccessSetsCookieWhenLoggedInWithNonRememberMeTokenInterfaceImplementation()
  215. {
  216. $service = $this->getService(null, array('name' => 'foo', 'domain' => 'myfoodomain.foo', 'path' => '/foo/path', 'secure' => true, 'httponly' => true, 'lifetime' => 3600, 'always_remember_me' => true));
  217. $request = new Request;
  218. $response = new Response;
  219. $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
  220. $account
  221. ->expects($this->once())
  222. ->method('getUsername')
  223. ->will($this->returnValue('foo'))
  224. ;
  225. $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
  226. $token
  227. ->expects($this->any())
  228. ->method('getUser')
  229. ->will($this->returnValue($account))
  230. ;
  231. $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
  232. $tokenProvider
  233. ->expects($this->once())
  234. ->method('createNewToken')
  235. ;
  236. $service->setTokenProvider($tokenProvider);
  237. $cookies = $response->headers->getCookies();
  238. $this->assertCount(0, $cookies);
  239. $service->loginSuccess($request, $response, $token);
  240. $cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
  241. $cookie = $cookies['myfoodomain.foo']['/foo/path']['foo'];
  242. $this->assertFalse($cookie->isCleared());
  243. $this->assertTrue($cookie->isSecure());
  244. $this->assertTrue($cookie->isHttpOnly());
  245. $this->assertTrue($cookie->getExpiresTime() > time() + 3590 && $cookie->getExpiresTime() < time() + 3610);
  246. $this->assertEquals('myfoodomain.foo', $cookie->getDomain());
  247. $this->assertEquals('/foo/path', $cookie->getPath());
  248. }
  249. protected function encodeCookie(array $parts)
  250. {
  251. $service = $this->getService();
  252. $r = new \ReflectionMethod($service, 'encodeCookie');
  253. $r->setAccessible(true);
  254. return $r->invoke($service, $parts);
  255. }
  256. protected function getService($userProvider = null, $options = array(), $logger = null)
  257. {
  258. if (null === $userProvider) {
  259. $userProvider = $this->getProvider();
  260. }
  261. return new PersistentTokenBasedRememberMeServices(array($userProvider), 'fookey', 'fookey', $options, $logger, new SecureRandom(sys_get_temp_dir().'/_sf2.seed'));
  262. }
  263. protected function getProvider()
  264. {
  265. $provider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
  266. $provider
  267. ->expects($this->any())
  268. ->method('supportsClass')
  269. ->will($this->returnValue(true))
  270. ;
  271. return $provider;
  272. }
  273. }