AuthGuardTest.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. <?php
  2. namespace Illuminate\Tests\Auth;
  3. use Illuminate\Auth\AuthenticationException;
  4. use Illuminate\Auth\Events\Attempting;
  5. use Illuminate\Auth\Events\Authenticated;
  6. use Illuminate\Auth\Events\CurrentDeviceLogout;
  7. use Illuminate\Auth\Events\Failed;
  8. use Illuminate\Auth\Events\Login;
  9. use Illuminate\Auth\Events\Logout;
  10. use Illuminate\Auth\Events\Validated;
  11. use Illuminate\Auth\SessionGuard;
  12. use Illuminate\Contracts\Auth\Authenticatable;
  13. use Illuminate\Contracts\Auth\UserProvider;
  14. use Illuminate\Contracts\Events\Dispatcher;
  15. use Illuminate\Contracts\Session\Session;
  16. use Illuminate\Cookie\CookieJar;
  17. use Illuminate\Support\Timebox;
  18. use Mockery as m;
  19. use PHPUnit\Framework\TestCase;
  20. use Symfony\Component\HttpFoundation\Cookie;
  21. use Symfony\Component\HttpFoundation\Request;
  22. use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
  23. class AuthGuardTest extends TestCase
  24. {
  25. protected function tearDown(): void
  26. {
  27. m::close();
  28. }
  29. public function testBasicReturnsNullOnValidAttempt()
  30. {
  31. [$session, $provider, $request, $cookie] = $this->getMocks();
  32. $guard = m::mock(SessionGuard::class.'[check,attempt]', ['default', $provider, $session]);
  33. $guard->shouldReceive('check')->once()->andReturn(false);
  34. $guard->shouldReceive('attempt')->once()->with(['email' => 'foo@bar.com', 'password' => 'secret'])->andReturn(true);
  35. $request = Request::create('/', 'GET', [], [], [], ['PHP_AUTH_USER' => 'foo@bar.com', 'PHP_AUTH_PW' => 'secret']);
  36. $guard->setRequest($request);
  37. $guard->basic('email');
  38. }
  39. public function testBasicReturnsNullWhenAlreadyLoggedIn()
  40. {
  41. [$session, $provider, $request, $cookie] = $this->getMocks();
  42. $guard = m::mock(SessionGuard::class.'[check]', ['default', $provider, $session]);
  43. $guard->shouldReceive('check')->once()->andReturn(true);
  44. $guard->shouldReceive('attempt')->never();
  45. $request = Request::create('/', 'GET', [], [], [], ['PHP_AUTH_USER' => 'foo@bar.com', 'PHP_AUTH_PW' => 'secret']);
  46. $guard->setRequest($request);
  47. $guard->basic('email');
  48. }
  49. public function testBasicReturnsResponseOnFailure()
  50. {
  51. $this->expectException(UnauthorizedHttpException::class);
  52. [$session, $provider, $request, $cookie] = $this->getMocks();
  53. $guard = m::mock(SessionGuard::class.'[check,attempt]', ['default', $provider, $session]);
  54. $guard->shouldReceive('check')->once()->andReturn(false);
  55. $guard->shouldReceive('attempt')->once()->with(['email' => 'foo@bar.com', 'password' => 'secret'])->andReturn(false);
  56. $request = Request::create('/', 'GET', [], [], [], ['PHP_AUTH_USER' => 'foo@bar.com', 'PHP_AUTH_PW' => 'secret']);
  57. $guard->setRequest($request);
  58. $guard->basic('email');
  59. }
  60. public function testBasicWithExtraConditions()
  61. {
  62. [$session, $provider, $request, $cookie] = $this->getMocks();
  63. $guard = m::mock(SessionGuard::class.'[check,attempt]', ['default', $provider, $session]);
  64. $guard->shouldReceive('check')->once()->andReturn(false);
  65. $guard->shouldReceive('attempt')->once()->with(['email' => 'foo@bar.com', 'password' => 'secret', 'active' => 1])->andReturn(true);
  66. $request = Request::create('/', 'GET', [], [], [], ['PHP_AUTH_USER' => 'foo@bar.com', 'PHP_AUTH_PW' => 'secret']);
  67. $guard->setRequest($request);
  68. $guard->basic('email', ['active' => 1]);
  69. }
  70. public function testBasicWithExtraArrayConditions()
  71. {
  72. [$session, $provider, $request, $cookie] = $this->getMocks();
  73. $guard = m::mock(SessionGuard::class.'[check,attempt]', ['default', $provider, $session]);
  74. $guard->shouldReceive('check')->once()->andReturn(false);
  75. $guard->shouldReceive('attempt')->once()->with(['email' => 'foo@bar.com', 'password' => 'secret', 'active' => 1, 'type' => [1, 2, 3]])->andReturn(true);
  76. $request = Request::create('/', 'GET', [], [], [], ['PHP_AUTH_USER' => 'foo@bar.com', 'PHP_AUTH_PW' => 'secret']);
  77. $guard->setRequest($request);
  78. $guard->basic('email', ['active' => 1, 'type' => [1, 2, 3]]);
  79. }
  80. public function testAttemptCallsRetrieveByCredentials()
  81. {
  82. $guard = $this->getGuard();
  83. $guard->setDispatcher($events = m::mock(Dispatcher::class));
  84. $timebox = $guard->getTimebox();
  85. $timebox->shouldReceive('call')->once()->andReturnUsing(function ($callback) use ($timebox) {
  86. return $callback($timebox);
  87. });
  88. $events->shouldReceive('dispatch')->once()->with(m::type(Attempting::class));
  89. $events->shouldReceive('dispatch')->once()->with(m::type(Failed::class));
  90. $events->shouldNotReceive('dispatch')->with(m::type(Validated::class));
  91. $guard->getProvider()->shouldReceive('retrieveByCredentials')->once()->with(['foo']);
  92. $guard->attempt(['foo']);
  93. }
  94. public function testAttemptReturnsUserInterface()
  95. {
  96. [$session, $provider, $request, $cookie, $timebox] = $this->getMocks();
  97. $guard = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['login'])->setConstructorArgs(['default', $provider, $session, $request, $timebox])->getMock();
  98. $guard->setDispatcher($events = m::mock(Dispatcher::class));
  99. $timebox->shouldReceive('call')->once()->andReturnUsing(function ($callback, $microseconds) use ($timebox) {
  100. return $callback($timebox->shouldReceive('returnEarly')->once()->getMock());
  101. });
  102. $events->shouldReceive('dispatch')->once()->with(m::type(Attempting::class));
  103. $events->shouldReceive('dispatch')->once()->with(m::type(Validated::class));
  104. $user = $this->createMock(Authenticatable::class);
  105. $guard->getProvider()->shouldReceive('retrieveByCredentials')->once()->andReturn($user);
  106. $guard->getProvider()->shouldReceive('validateCredentials')->with($user, ['foo'])->andReturn(true);
  107. $guard->expects($this->once())->method('login')->with($this->equalTo($user));
  108. $this->assertTrue($guard->attempt(['foo']));
  109. }
  110. public function testAttemptReturnsFalseIfUserNotGiven()
  111. {
  112. $mock = $this->getGuard();
  113. $mock->setDispatcher($events = m::mock(Dispatcher::class));
  114. $timebox = $mock->getTimebox();
  115. $timebox->shouldReceive('call')->once()->andReturnUsing(function ($callback, $microseconds) use ($timebox) {
  116. return $callback($timebox);
  117. });
  118. $events->shouldReceive('dispatch')->once()->with(m::type(Attempting::class));
  119. $events->shouldReceive('dispatch')->once()->with(m::type(Failed::class));
  120. $events->shouldNotReceive('dispatch')->with(m::type(Validated::class));
  121. $mock->getProvider()->shouldReceive('retrieveByCredentials')->once()->andReturn(null);
  122. $this->assertFalse($mock->attempt(['foo']));
  123. }
  124. public function testAttemptAndWithCallbacks()
  125. {
  126. [$session, $provider, $request, $cookie, $timebox] = $this->getMocks();
  127. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['getName'])->setConstructorArgs(['default', $provider, $session, $request, $timebox])->getMock();
  128. $mock->setDispatcher($events = m::mock(Dispatcher::class));
  129. $timebox->shouldReceive('call')->andReturnUsing(function ($callback) use ($timebox) {
  130. return $callback($timebox->shouldReceive('returnEarly')->getMock());
  131. });
  132. $user = m::mock(Authenticatable::class);
  133. $events->shouldReceive('dispatch')->times(3)->with(m::type(Attempting::class));
  134. $events->shouldReceive('dispatch')->once()->with(m::type(Login::class));
  135. $events->shouldReceive('dispatch')->once()->with(m::type(Authenticated::class));
  136. $events->shouldReceive('dispatch')->twice()->with(m::type(Validated::class));
  137. $events->shouldReceive('dispatch')->twice()->with(m::type(Failed::class));
  138. $mock->expects($this->once())->method('getName')->willReturn('foo');
  139. $user->shouldReceive('getAuthIdentifier')->once()->andReturn('bar');
  140. $mock->getSession()->shouldReceive('put')->with('foo', 'bar')->once();
  141. $session->shouldReceive('migrate')->once();
  142. $mock->getProvider()->shouldReceive('retrieveByCredentials')->times(3)->with(['foo'])->andReturn($user);
  143. $mock->getProvider()->shouldReceive('validateCredentials')->twice()->andReturnTrue();
  144. $mock->getProvider()->shouldReceive('validateCredentials')->once()->andReturnFalse();
  145. $this->assertTrue($mock->attemptWhen(['foo'], function ($user, $guard) {
  146. static::assertInstanceOf(Authenticatable::class, $user);
  147. static::assertInstanceOf(SessionGuard::class, $guard);
  148. return true;
  149. }));
  150. $this->assertFalse($mock->attemptWhen(['foo'], function ($user, $guard) {
  151. static::assertInstanceOf(Authenticatable::class, $user);
  152. static::assertInstanceOf(SessionGuard::class, $guard);
  153. return false;
  154. }));
  155. $executed = false;
  156. $this->assertFalse($mock->attemptWhen(['foo'], false, function () use (&$executed) {
  157. return $executed = true;
  158. }));
  159. $this->assertFalse($executed);
  160. }
  161. public function testLoginStoresIdentifierInSession()
  162. {
  163. [$session, $provider, $request, $cookie] = $this->getMocks();
  164. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['getName'])->setConstructorArgs(['default', $provider, $session, $request])->getMock();
  165. $user = m::mock(Authenticatable::class);
  166. $mock->expects($this->once())->method('getName')->willReturn('foo');
  167. $user->shouldReceive('getAuthIdentifier')->once()->andReturn('bar');
  168. $mock->getSession()->shouldReceive('put')->with('foo', 'bar')->once();
  169. $session->shouldReceive('migrate')->once();
  170. $mock->login($user);
  171. }
  172. public function testSessionGuardIsMacroable()
  173. {
  174. $guard = $this->getGuard();
  175. $guard->macro('foo', function () {
  176. return 'bar';
  177. });
  178. $this->assertSame(
  179. 'bar', $guard->foo()
  180. );
  181. }
  182. public function testLoginFiresLoginAndAuthenticatedEvents()
  183. {
  184. [$session, $provider, $request, $cookie] = $this->getMocks();
  185. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['getName'])->setConstructorArgs(['default', $provider, $session, $request])->getMock();
  186. $mock->setDispatcher($events = m::mock(Dispatcher::class));
  187. $user = m::mock(Authenticatable::class);
  188. $events->shouldReceive('dispatch')->once()->with(m::type(Login::class));
  189. $events->shouldReceive('dispatch')->once()->with(m::type(Authenticated::class));
  190. $mock->expects($this->once())->method('getName')->willReturn('foo');
  191. $user->shouldReceive('getAuthIdentifier')->once()->andReturn('bar');
  192. $mock->getSession()->shouldReceive('put')->with('foo', 'bar')->once();
  193. $session->shouldReceive('migrate')->once();
  194. $mock->login($user);
  195. }
  196. public function testFailedAttemptFiresFailedEvent()
  197. {
  198. $guard = $this->getGuard();
  199. $guard->setDispatcher($events = m::mock(Dispatcher::class));
  200. $timebox = $guard->getTimebox();
  201. $timebox->shouldReceive('call')->once()->andReturnUsing(function ($callback, $microseconds) use ($timebox) {
  202. return $callback($timebox);
  203. });
  204. $events->shouldReceive('dispatch')->once()->with(m::type(Attempting::class));
  205. $events->shouldReceive('dispatch')->once()->with(m::type(Failed::class));
  206. $events->shouldNotReceive('dispatch')->with(m::type(Validated::class));
  207. $guard->getProvider()->shouldReceive('retrieveByCredentials')->once()->with(['foo'])->andReturn(null);
  208. $guard->attempt(['foo']);
  209. }
  210. public function testAuthenticateReturnsUserWhenUserIsNotNull()
  211. {
  212. $user = m::mock(Authenticatable::class);
  213. $guard = $this->getGuard()->setUser($user);
  214. $this->assertEquals($user, $guard->authenticate());
  215. }
  216. public function testSetUserFiresAuthenticatedEvent()
  217. {
  218. $user = m::mock(Authenticatable::class);
  219. $guard = $this->getGuard();
  220. $guard->setDispatcher($events = m::mock(Dispatcher::class));
  221. $events->shouldReceive('dispatch')->once()->with(m::type(Authenticated::class));
  222. $guard->setUser($user);
  223. }
  224. public function testAuthenticateThrowsWhenUserIsNull()
  225. {
  226. $this->expectException(AuthenticationException::class);
  227. $this->expectExceptionMessage('Unauthenticated.');
  228. $guard = $this->getGuard();
  229. $guard->getSession()->shouldReceive('get')->once()->andReturn(null);
  230. $guard->authenticate();
  231. }
  232. public function testHasUserReturnsTrueWhenUserIsNotNull()
  233. {
  234. $user = m::mock(Authenticatable::class);
  235. $guard = $this->getGuard()->setUser($user);
  236. $this->assertTrue($guard->hasUser());
  237. }
  238. public function testHasUserReturnsFalseWhenUserIsNull()
  239. {
  240. $guard = $this->getGuard();
  241. $guard->getSession()->shouldNotReceive('get');
  242. $this->assertFalse($guard->hasUser());
  243. }
  244. public function testIsAuthedReturnsTrueWhenUserIsNotNull()
  245. {
  246. $user = m::mock(Authenticatable::class);
  247. $mock = $this->getGuard();
  248. $mock->setUser($user);
  249. $this->assertTrue($mock->check());
  250. $this->assertFalse($mock->guest());
  251. }
  252. public function testIsAuthedReturnsFalseWhenUserIsNull()
  253. {
  254. [$session, $provider, $request, $cookie] = $this->getMocks();
  255. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['user'])->setConstructorArgs(['default', $provider, $session, $request])->getMock();
  256. $mock->expects($this->exactly(2))->method('user')->willReturn(null);
  257. $this->assertFalse($mock->check());
  258. $this->assertTrue($mock->guest());
  259. }
  260. public function testUserMethodReturnsCachedUser()
  261. {
  262. $user = m::mock(Authenticatable::class);
  263. $mock = $this->getGuard();
  264. $mock->setUser($user);
  265. $this->assertSame($user, $mock->user());
  266. }
  267. public function testNullIsReturnedForUserIfNoUserFound()
  268. {
  269. $mock = $this->getGuard();
  270. $mock->getSession()->shouldReceive('get')->once()->andReturn(null);
  271. $this->assertNull($mock->user());
  272. }
  273. public function testUserIsSetToRetrievedUser()
  274. {
  275. $mock = $this->getGuard();
  276. $mock->getSession()->shouldReceive('get')->once()->andReturn(1);
  277. $user = m::mock(Authenticatable::class);
  278. $mock->getProvider()->shouldReceive('retrieveById')->once()->with(1)->andReturn($user);
  279. $this->assertSame($user, $mock->user());
  280. $this->assertSame($user, $mock->getUser());
  281. }
  282. public function testLogoutRemovesSessionTokenAndRememberMeCookie()
  283. {
  284. [$session, $provider, $request, $cookie] = $this->getMocks();
  285. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['getName', 'getRecallerName', 'recaller'])->setConstructorArgs(['default', $provider, $session, $request])->getMock();
  286. $mock->setCookieJar($cookies = m::mock(CookieJar::class));
  287. $user = m::mock(Authenticatable::class);
  288. $user->shouldReceive('getRememberToken')->once()->andReturn('a');
  289. $user->shouldReceive('setRememberToken')->once();
  290. $mock->expects($this->once())->method('getName')->willReturn('foo');
  291. $mock->expects($this->once())->method('getRecallerName')->willReturn('bar');
  292. $mock->expects($this->once())->method('recaller')->willReturn('non-null-cookie');
  293. $provider->shouldReceive('updateRememberToken')->once();
  294. $cookie = m::mock(Cookie::class);
  295. $cookies->shouldReceive('forget')->once()->with('bar')->andReturn($cookie);
  296. $cookies->shouldReceive('queue')->once()->with($cookie);
  297. $mock->getSession()->shouldReceive('remove')->once()->with('foo');
  298. $mock->setUser($user);
  299. $mock->logout();
  300. $this->assertNull($mock->getUser());
  301. }
  302. public function testLogoutDoesNotEnqueueRememberMeCookieForDeletionIfCookieDoesntExist()
  303. {
  304. [$session, $provider, $request, $cookie] = $this->getMocks();
  305. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['getName', 'recaller'])->setConstructorArgs(['default', $provider, $session, $request])->getMock();
  306. $mock->setCookieJar($cookies = m::mock(CookieJar::class));
  307. $user = m::mock(Authenticatable::class);
  308. $user->shouldReceive('getRememberToken')->andReturn(null);
  309. $mock->expects($this->once())->method('getName')->willReturn('foo');
  310. $mock->expects($this->once())->method('recaller')->willReturn(null);
  311. $mock->getSession()->shouldReceive('remove')->once()->with('foo');
  312. $mock->setUser($user);
  313. $mock->logout();
  314. $this->assertNull($mock->getUser());
  315. }
  316. public function testLogoutFiresLogoutEvent()
  317. {
  318. [$session, $provider, $request, $cookie] = $this->getMocks();
  319. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['clearUserDataFromStorage'])->setConstructorArgs(['default', $provider, $session, $request])->getMock();
  320. $mock->expects($this->once())->method('clearUserDataFromStorage');
  321. $mock->setDispatcher($events = m::mock(Dispatcher::class));
  322. $user = m::mock(Authenticatable::class);
  323. $user->shouldReceive('getRememberToken')->andReturn(null);
  324. $events->shouldReceive('dispatch')->once()->with(m::type(Authenticated::class));
  325. $mock->setUser($user);
  326. $events->shouldReceive('dispatch')->once()->with(m::type(Logout::class));
  327. $mock->logout();
  328. }
  329. public function testLogoutDoesNotSetRememberTokenIfNotPreviouslySet()
  330. {
  331. [$session, $provider, $request] = $this->getMocks();
  332. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['clearUserDataFromStorage'])->setConstructorArgs(['default', $provider, $session, $request])->getMock();
  333. $user = m::mock(Authenticatable::class);
  334. $user->shouldReceive('getRememberToken')->andReturn(null);
  335. $user->shouldNotReceive('setRememberToken');
  336. $provider->shouldNotReceive('updateRememberToken');
  337. $mock->setUser($user);
  338. $mock->logout();
  339. }
  340. public function testLogoutCurrentDeviceRemovesRememberMeCookie()
  341. {
  342. [$session, $provider, $request, $cookie] = $this->getMocks();
  343. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['getName', 'getRecallerName', 'recaller'])->setConstructorArgs(['default', $provider, $session, $request])->getMock();
  344. $mock->setCookieJar($cookies = m::mock(CookieJar::class));
  345. $user = m::mock(Authenticatable::class);
  346. $mock->expects($this->once())->method('getName')->willReturn('foo');
  347. $mock->expects($this->once())->method('getRecallerName')->willReturn('bar');
  348. $mock->expects($this->once())->method('recaller')->willReturn('non-null-cookie');
  349. $cookie = m::mock(Cookie::class);
  350. $cookies->shouldReceive('forget')->once()->with('bar')->andReturn($cookie);
  351. $cookies->shouldReceive('queue')->once()->with($cookie);
  352. $mock->getSession()->shouldReceive('remove')->once()->with('foo');
  353. $mock->setUser($user);
  354. $mock->logoutCurrentDevice();
  355. $this->assertNull($mock->getUser());
  356. }
  357. public function testLogoutCurrentDeviceDoesNotEnqueueRememberMeCookieForDeletionIfCookieDoesntExist()
  358. {
  359. [$session, $provider, $request, $cookie] = $this->getMocks();
  360. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['getName', 'recaller'])->setConstructorArgs(['default', $provider, $session, $request])->getMock();
  361. $mock->setCookieJar($cookies = m::mock(CookieJar::class));
  362. $user = m::mock(Authenticatable::class);
  363. $user->shouldReceive('getRememberToken')->andReturn(null);
  364. $mock->expects($this->once())->method('getName')->willReturn('foo');
  365. $mock->expects($this->once())->method('recaller')->willReturn(null);
  366. $mock->getSession()->shouldReceive('remove')->once()->with('foo');
  367. $mock->setUser($user);
  368. $mock->logoutCurrentDevice();
  369. $this->assertNull($mock->getUser());
  370. }
  371. public function testLogoutCurrentDeviceFiresLogoutEvent()
  372. {
  373. [$session, $provider, $request, $cookie] = $this->getMocks();
  374. $mock = $this->getMockBuilder(SessionGuard::class)->onlyMethods(['clearUserDataFromStorage'])->setConstructorArgs(['default', $provider, $session, $request])->getMock();
  375. $mock->expects($this->once())->method('clearUserDataFromStorage');
  376. $mock->setDispatcher($events = m::mock(Dispatcher::class));
  377. $user = m::mock(Authenticatable::class);
  378. $user->shouldReceive('getRememberToken')->andReturn(null);
  379. $events->shouldReceive('dispatch')->once()->with(m::type(Authenticated::class));
  380. $mock->setUser($user);
  381. $events->shouldReceive('dispatch')->once()->with(m::type(CurrentDeviceLogout::class));
  382. $mock->logoutCurrentDevice();
  383. }
  384. public function testLoginMethodQueuesCookieWhenRemembering()
  385. {
  386. [$session, $provider, $request, $cookie] = $this->getMocks();
  387. $guard = new SessionGuard('default', $provider, $session, $request);
  388. $guard->setCookieJar($cookie);
  389. $foreverCookie = new Cookie($guard->getRecallerName(), 'foo');
  390. $cookie->shouldReceive('make')->once()->with($guard->getRecallerName(), 'foo|recaller|bar', 2628000)->andReturn($foreverCookie);
  391. $cookie->shouldReceive('queue')->once()->with($foreverCookie);
  392. $guard->getSession()->shouldReceive('put')->once()->with($guard->getName(), 'foo');
  393. $session->shouldReceive('migrate')->once();
  394. $user = m::mock(Authenticatable::class);
  395. $user->shouldReceive('getAuthIdentifier')->andReturn('foo');
  396. $user->shouldReceive('getAuthPassword')->andReturn('bar');
  397. $user->shouldReceive('getRememberToken')->andReturn('recaller');
  398. $user->shouldReceive('setRememberToken')->never();
  399. $provider->shouldReceive('updateRememberToken')->never();
  400. $guard->login($user, true);
  401. }
  402. public function testLoginMethodQueuesCookieWhenRememberingAndAllowsOverride()
  403. {
  404. [$session, $provider, $request, $cookie] = $this->getMocks();
  405. $guard = new SessionGuard('default', $provider, $session, $request);
  406. $guard->setRememberDuration(5000);
  407. $guard->setCookieJar($cookie);
  408. $foreverCookie = new Cookie($guard->getRecallerName(), 'foo');
  409. $cookie->shouldReceive('make')->once()->with($guard->getRecallerName(), 'foo|recaller|bar', 5000)->andReturn($foreverCookie);
  410. $cookie->shouldReceive('queue')->once()->with($foreverCookie);
  411. $guard->getSession()->shouldReceive('put')->once()->with($guard->getName(), 'foo');
  412. $session->shouldReceive('migrate')->once();
  413. $user = m::mock(Authenticatable::class);
  414. $user->shouldReceive('getAuthIdentifier')->andReturn('foo');
  415. $user->shouldReceive('getAuthPassword')->andReturn('bar');
  416. $user->shouldReceive('getRememberToken')->andReturn('recaller');
  417. $user->shouldReceive('setRememberToken')->never();
  418. $provider->shouldReceive('updateRememberToken')->never();
  419. $guard->login($user, true);
  420. }
  421. public function testLoginMethodCreatesRememberTokenIfOneDoesntExist()
  422. {
  423. [$session, $provider, $request, $cookie] = $this->getMocks();
  424. $guard = new SessionGuard('default', $provider, $session, $request);
  425. $guard->setCookieJar($cookie);
  426. $foreverCookie = new Cookie($guard->getRecallerName(), 'foo');
  427. $cookie->shouldReceive('make')->once()->andReturn($foreverCookie);
  428. $cookie->shouldReceive('queue')->once()->with($foreverCookie);
  429. $guard->getSession()->shouldReceive('put')->once()->with($guard->getName(), 'foo');
  430. $session->shouldReceive('migrate')->once();
  431. $user = m::mock(Authenticatable::class);
  432. $user->shouldReceive('getAuthIdentifier')->andReturn('foo');
  433. $user->shouldReceive('getAuthPassword')->andReturn('foo');
  434. $user->shouldReceive('getRememberToken')->andReturn(null);
  435. $user->shouldReceive('setRememberToken')->once();
  436. $provider->shouldReceive('updateRememberToken')->once();
  437. $guard->login($user, true);
  438. }
  439. public function testLoginUsingIdLogsInWithUser()
  440. {
  441. [$session, $provider, $request, $cookie] = $this->getMocks();
  442. $guard = m::mock(SessionGuard::class, ['default', $provider, $session])->makePartial();
  443. $user = m::mock(Authenticatable::class);
  444. $guard->getProvider()->shouldReceive('retrieveById')->once()->with(10)->andReturn($user);
  445. $guard->shouldReceive('login')->once()->with($user, false);
  446. $this->assertSame($user, $guard->loginUsingId(10));
  447. }
  448. public function testLoginUsingIdFailure()
  449. {
  450. [$session, $provider, $request, $cookie] = $this->getMocks();
  451. $guard = m::mock(SessionGuard::class, ['default', $provider, $session])->makePartial();
  452. $guard->getProvider()->shouldReceive('retrieveById')->once()->with(11)->andReturn(null);
  453. $guard->shouldNotReceive('login');
  454. $this->assertFalse($guard->loginUsingId(11));
  455. }
  456. public function testOnceUsingIdSetsUser()
  457. {
  458. [$session, $provider, $request, $cookie] = $this->getMocks();
  459. $guard = m::mock(SessionGuard::class, ['default', $provider, $session])->makePartial();
  460. $user = m::mock(Authenticatable::class);
  461. $guard->getProvider()->shouldReceive('retrieveById')->once()->with(10)->andReturn($user);
  462. $guard->shouldReceive('setUser')->once()->with($user);
  463. $this->assertSame($user, $guard->onceUsingId(10));
  464. }
  465. public function testOnceUsingIdFailure()
  466. {
  467. [$session, $provider, $request, $cookie] = $this->getMocks();
  468. $guard = m::mock(SessionGuard::class, ['default', $provider, $session])->makePartial();
  469. $guard->getProvider()->shouldReceive('retrieveById')->once()->with(11)->andReturn(null);
  470. $guard->shouldNotReceive('setUser');
  471. $this->assertFalse($guard->onceUsingId(11));
  472. }
  473. public function testUserUsesRememberCookieIfItExists()
  474. {
  475. $guard = $this->getGuard();
  476. [$session, $provider, $request, $cookie] = $this->getMocks();
  477. $request = Request::create('/', 'GET', [], [$guard->getRecallerName() => 'id|recaller|baz']);
  478. $guard = new SessionGuard('default', $provider, $session, $request);
  479. $guard->getSession()->shouldReceive('get')->once()->with($guard->getName())->andReturn(null);
  480. $user = m::mock(Authenticatable::class);
  481. $guard->getProvider()->shouldReceive('retrieveByToken')->once()->with('id', 'recaller')->andReturn($user);
  482. $user->shouldReceive('getAuthIdentifier')->once()->andReturn('bar');
  483. $guard->getSession()->shouldReceive('put')->with($guard->getName(), 'bar')->once();
  484. $session->shouldReceive('migrate')->once();
  485. $this->assertSame($user, $guard->user());
  486. $this->assertTrue($guard->viaRemember());
  487. }
  488. public function testLoginOnceSetsUser()
  489. {
  490. [$session, $provider, $request, $cookie, $timebox] = $this->getMocks();
  491. $guard = m::mock(SessionGuard::class, ['default', $provider, $session, $request, $timebox])->makePartial();
  492. $user = m::mock(Authenticatable::class);
  493. $timebox->shouldReceive('call')->once()->andReturnUsing(function ($callback) use ($timebox) {
  494. return $callback($timebox->shouldReceive('returnEarly')->once()->getMock());
  495. });
  496. $guard->getProvider()->shouldReceive('retrieveByCredentials')->once()->with(['foo'])->andReturn($user);
  497. $guard->getProvider()->shouldReceive('validateCredentials')->once()->with($user, ['foo'])->andReturn(true);
  498. $guard->shouldReceive('setUser')->once()->with($user);
  499. $this->assertTrue($guard->once(['foo']));
  500. }
  501. public function testLoginOnceFailure()
  502. {
  503. [$session, $provider, $request, $cookie, $timebox] = $this->getMocks();
  504. $guard = m::mock(SessionGuard::class, ['default', $provider, $session, $request, $timebox])->makePartial();
  505. $user = m::mock(Authenticatable::class);
  506. $timebox->shouldReceive('call')->once()->andReturnUsing(function ($callback) use ($timebox) {
  507. return $callback($timebox);
  508. });
  509. $guard->getProvider()->shouldReceive('retrieveByCredentials')->once()->with(['foo'])->andReturn($user);
  510. $guard->getProvider()->shouldReceive('validateCredentials')->once()->with($user, ['foo'])->andReturn(false);
  511. $this->assertFalse($guard->once(['foo']));
  512. }
  513. protected function getGuard()
  514. {
  515. [$session, $provider, $request, $cookie, $timebox] = $this->getMocks();
  516. return new SessionGuard('default', $provider, $session, $request, $timebox);
  517. }
  518. protected function getMocks()
  519. {
  520. return [
  521. m::mock(Session::class),
  522. m::mock(UserProvider::class),
  523. Request::create('/', 'GET'),
  524. m::mock(CookieJar::class),
  525. m::mock(Timebox::class),
  526. ];
  527. }
  528. protected function getCookieJar()
  529. {
  530. return new CookieJar(Request::create('/foo', 'GET'), m::mock(Encrypter::class), ['domain' => 'foo.com', 'path' => '/', 'secure' => false, 'httpOnly' => false]);
  531. }
  532. }