LoginControllerTest.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. <?php
  2. /**
  3. * @author Lukas Reschke <lukas@owncloud.com>
  4. *
  5. * @copyright Copyright (c) 2016, ownCloud, Inc.
  6. * @license AGPL-3.0
  7. *
  8. * This code is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License, version 3,
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License, version 3,
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>
  19. *
  20. */
  21. namespace Tests\Core\Controller;
  22. use OC\Authentication\TwoFactorAuth\Manager;
  23. use OC\Core\Controller\LoginController;
  24. use OC\Security\Bruteforce\Throttler;
  25. use OCP\AppFramework\Http\RedirectResponse;
  26. use OCP\AppFramework\Http\TemplateResponse;
  27. use OCP\IConfig;
  28. use OCP\IRequest;
  29. use OCP\ISession;
  30. use OCP\IURLGenerator;
  31. use OCP\IUser;
  32. use OCP\IUserManager;
  33. use OCP\IUserSession;
  34. use Test\TestCase;
  35. class LoginControllerTest extends TestCase {
  36. /** @var LoginController */
  37. private $loginController;
  38. /** @var IRequest | \PHPUnit_Framework_MockObject_MockObject */
  39. private $request;
  40. /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */
  41. private $userManager;
  42. /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */
  43. private $config;
  44. /** @var ISession | \PHPUnit_Framework_MockObject_MockObject */
  45. private $session;
  46. /** @var IUserSession | \PHPUnit_Framework_MockObject_MockObject */
  47. private $userSession;
  48. /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject */
  49. private $urlGenerator;
  50. /** @var Manager | \PHPUnit_Framework_MockObject_MockObject */
  51. private $twoFactorManager;
  52. /** @var Throttler */
  53. private $throttler;
  54. public function setUp() {
  55. parent::setUp();
  56. $this->request = $this->getMockBuilder('\\OCP\\IRequest')->getMock();
  57. $this->userManager = $this->getMockBuilder('\\OCP\\IUserManager')->getMock();
  58. $this->config = $this->getMockBuilder('\\OCP\\IConfig')->getMock();
  59. $this->session = $this->getMockBuilder('\\OCP\\ISession')->getMock();
  60. $this->userSession = $this->getMockBuilder('\\OC\\User\\Session')
  61. ->disableOriginalConstructor()
  62. ->getMock();
  63. $this->urlGenerator = $this->getMockBuilder('\\OCP\\IURLGenerator')->getMock();
  64. $this->twoFactorManager = $this->getMockBuilder('\OC\Authentication\TwoFactorAuth\Manager')
  65. ->disableOriginalConstructor()
  66. ->getMock();
  67. $this->throttler = $this->getMockBuilder('\OC\Security\Bruteforce\Throttler')
  68. ->disableOriginalConstructor()
  69. ->getMock();
  70. $this->loginController = new LoginController(
  71. 'core',
  72. $this->request,
  73. $this->userManager,
  74. $this->config,
  75. $this->session,
  76. $this->userSession,
  77. $this->urlGenerator,
  78. $this->twoFactorManager,
  79. $this->throttler
  80. );
  81. }
  82. public function testLogoutWithoutToken() {
  83. $this->request
  84. ->expects($this->once())
  85. ->method('getCookie')
  86. ->with('oc_token')
  87. ->willReturn(null);
  88. $this->config
  89. ->expects($this->never())
  90. ->method('deleteUserValue');
  91. $this->urlGenerator
  92. ->expects($this->once())
  93. ->method('linkToRouteAbsolute')
  94. ->with('core.login.showLoginForm')
  95. ->willReturn('/login');
  96. $expected = new RedirectResponse('/login');
  97. $this->assertEquals($expected, $this->loginController->logout());
  98. }
  99. public function testLogoutWithToken() {
  100. $this->request
  101. ->expects($this->once())
  102. ->method('getCookie')
  103. ->with('oc_token')
  104. ->willReturn('MyLoginToken');
  105. $user = $this->getMockBuilder('\\OCP\\IUser')->getMock();
  106. $user
  107. ->expects($this->once())
  108. ->method('getUID')
  109. ->willReturn('JohnDoe');
  110. $this->userSession
  111. ->expects($this->once())
  112. ->method('getUser')
  113. ->willReturn($user);
  114. $this->config
  115. ->expects($this->once())
  116. ->method('deleteUserValue')
  117. ->with('JohnDoe', 'login_token', 'MyLoginToken');
  118. $this->urlGenerator
  119. ->expects($this->once())
  120. ->method('linkToRouteAbsolute')
  121. ->with('core.login.showLoginForm')
  122. ->willReturn('/login');
  123. $expected = new RedirectResponse('/login');
  124. $this->assertEquals($expected, $this->loginController->logout());
  125. }
  126. public function testShowLoginFormForLoggedInUsers() {
  127. $this->userSession
  128. ->expects($this->once())
  129. ->method('isLoggedIn')
  130. ->willReturn(true);
  131. $expectedResponse = new RedirectResponse(\OC_Util::getDefaultPageUrl());
  132. $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('', '', ''));
  133. }
  134. public function testShowLoginFormWithErrorsInSession() {
  135. $this->userSession
  136. ->expects($this->once())
  137. ->method('isLoggedIn')
  138. ->willReturn(false);
  139. $this->session
  140. ->expects($this->once())
  141. ->method('get')
  142. ->with('loginMessages')
  143. ->willReturn(
  144. [
  145. [
  146. 'ErrorArray1',
  147. 'ErrorArray2',
  148. ],
  149. [
  150. 'MessageArray1',
  151. 'MessageArray2',
  152. ],
  153. ]
  154. );
  155. $expectedResponse = new TemplateResponse(
  156. 'core',
  157. 'login',
  158. [
  159. 'ErrorArray1' => true,
  160. 'ErrorArray2' => true,
  161. 'messages' => [
  162. 'MessageArray1',
  163. 'MessageArray2',
  164. ],
  165. 'loginName' => '',
  166. 'user_autofocus' => true,
  167. 'canResetPassword' => true,
  168. 'alt_login' => [],
  169. 'rememberLoginAllowed' => \OC_Util::rememberLoginAllowed(),
  170. 'rememberLoginState' => 0,
  171. 'resetPasswordLink' => null,
  172. ],
  173. 'guest'
  174. );
  175. $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('', '', ''));
  176. }
  177. /**
  178. * @return array
  179. */
  180. public function passwordResetDataProvider() {
  181. return [
  182. [
  183. true,
  184. true,
  185. ],
  186. [
  187. false,
  188. false,
  189. ],
  190. ];
  191. }
  192. /**
  193. * @dataProvider passwordResetDataProvider
  194. */
  195. public function testShowLoginFormWithPasswordResetOption($canChangePassword,
  196. $expectedResult) {
  197. $this->userSession
  198. ->expects($this->once())
  199. ->method('isLoggedIn')
  200. ->willReturn(false);
  201. $this->config
  202. ->expects($this->once())
  203. ->method('getSystemValue')
  204. ->with('lost_password_link')
  205. ->willReturn(false);
  206. $user = $this->getMockBuilder('\\OCP\\IUser')->getMock();
  207. $user
  208. ->expects($this->once())
  209. ->method('canChangePassword')
  210. ->willReturn($canChangePassword);
  211. $this->userManager
  212. ->expects($this->once())
  213. ->method('get')
  214. ->with('LdapUser')
  215. ->willReturn($user);
  216. $expectedResponse = new TemplateResponse(
  217. 'core',
  218. 'login',
  219. [
  220. 'messages' => [],
  221. 'loginName' => 'LdapUser',
  222. 'user_autofocus' => false,
  223. 'canResetPassword' => $expectedResult,
  224. 'alt_login' => [],
  225. 'rememberLoginAllowed' => \OC_Util::rememberLoginAllowed(),
  226. 'rememberLoginState' => 0,
  227. 'resetPasswordLink' => false,
  228. ],
  229. 'guest'
  230. );
  231. $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('LdapUser', '', ''));
  232. }
  233. public function testShowLoginFormForUserNamedNull() {
  234. $this->userSession
  235. ->expects($this->once())
  236. ->method('isLoggedIn')
  237. ->willReturn(false);
  238. $this->config
  239. ->expects($this->once())
  240. ->method('getSystemValue')
  241. ->with('lost_password_link')
  242. ->willReturn(false);
  243. $user = $this->getMockBuilder('\\OCP\\IUser')->getMock();
  244. $user
  245. ->expects($this->once())
  246. ->method('canChangePassword')
  247. ->willReturn(false);
  248. $this->userManager
  249. ->expects($this->once())
  250. ->method('get')
  251. ->with('0')
  252. ->willReturn($user);
  253. $expectedResponse = new TemplateResponse(
  254. 'core',
  255. 'login',
  256. [
  257. 'messages' => [],
  258. 'loginName' => '0',
  259. 'user_autofocus' => false,
  260. 'canResetPassword' => false,
  261. 'alt_login' => [],
  262. 'rememberLoginAllowed' => \OC_Util::rememberLoginAllowed(),
  263. 'rememberLoginState' => 0,
  264. 'resetPasswordLink' => false,
  265. ],
  266. 'guest'
  267. );
  268. $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('0', '', ''));
  269. }
  270. public function testLoginWithInvalidCredentials() {
  271. $user = 'MyUserName';
  272. $password = 'secret';
  273. $loginPageUrl = 'some url';
  274. $this->request
  275. ->expects($this->exactly(4))
  276. ->method('getRemoteAddress')
  277. ->willReturn('192.168.0.1');
  278. $this->request
  279. ->expects($this->once())
  280. ->method('passesCSRFCheck')
  281. ->willReturn(true);
  282. $this->throttler
  283. ->expects($this->exactly(2))
  284. ->method('sleepDelay')
  285. ->with('192.168.0.1');
  286. $this->throttler
  287. ->expects($this->once())
  288. ->method('getDelay')
  289. ->with('192.168.0.1')
  290. ->willReturn(0);
  291. $this->throttler
  292. ->expects($this->once())
  293. ->method('registerAttempt')
  294. ->with('login', '192.168.0.1', ['user' => 'MyUserName']);
  295. $this->userManager->expects($this->once())
  296. ->method('checkPassword')
  297. ->will($this->returnValue(false));
  298. $this->urlGenerator->expects($this->once())
  299. ->method('linkToRoute')
  300. ->with('core.login.showLoginForm')
  301. ->will($this->returnValue($loginPageUrl));
  302. $this->userSession->expects($this->never())
  303. ->method('createSessionToken');
  304. $this->userSession->expects($this->never())
  305. ->method('createRememberMeToken');
  306. $this->config->expects($this->never())
  307. ->method('deleteUserValue');
  308. $expected = new \OCP\AppFramework\Http\RedirectResponse($loginPageUrl);
  309. $this->assertEquals($expected, $this->loginController->tryLogin($user, $password, ''));
  310. }
  311. public function testLoginWithValidCredentials() {
  312. /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */
  313. $user = $this->getMockBuilder('\OCP\IUser')->getMock();
  314. $user->expects($this->any())
  315. ->method('getUID')
  316. ->will($this->returnValue('uid'));
  317. $password = 'secret';
  318. $indexPageUrl = \OC_Util::getDefaultPageUrl();
  319. $this->request
  320. ->expects($this->exactly(2))
  321. ->method('getRemoteAddress')
  322. ->willReturn('192.168.0.1');
  323. $this->request
  324. ->expects($this->once())
  325. ->method('passesCSRFCheck')
  326. ->willReturn(true);
  327. $this->throttler
  328. ->expects($this->once())
  329. ->method('sleepDelay')
  330. ->with('192.168.0.1');
  331. $this->throttler
  332. ->expects($this->once())
  333. ->method('getDelay')
  334. ->with('192.168.0.1')
  335. ->willReturn(200);
  336. $this->userManager->expects($this->once())
  337. ->method('checkPassword')
  338. ->will($this->returnValue($user));
  339. $this->userSession->expects($this->once())
  340. ->method('login')
  341. ->with($user, $password);
  342. $this->userSession->expects($this->once())
  343. ->method('createSessionToken')
  344. ->with($this->request, $user->getUID(), $user, $password, false);
  345. $this->twoFactorManager->expects($this->once())
  346. ->method('isTwoFactorAuthenticated')
  347. ->with($user)
  348. ->will($this->returnValue(false));
  349. $this->config->expects($this->once())
  350. ->method('deleteUserValue')
  351. ->with('uid', 'core', 'lostpassword');
  352. $this->userSession->expects($this->never())
  353. ->method('createRememberMeToken');
  354. $expected = new \OCP\AppFramework\Http\RedirectResponse($indexPageUrl);
  355. $this->assertEquals($expected, $this->loginController->tryLogin($user, $password, null));
  356. }
  357. public function testLoginWithValidCredentialsAndRememberMe() {
  358. /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */
  359. $user = $this->getMockBuilder('\OCP\IUser')->getMock();
  360. $user->expects($this->any())
  361. ->method('getUID')
  362. ->will($this->returnValue('uid'));
  363. $password = 'secret';
  364. $indexPageUrl = \OC_Util::getDefaultPageUrl();
  365. $this->request
  366. ->expects($this->exactly(2))
  367. ->method('getRemoteAddress')
  368. ->willReturn('192.168.0.1');
  369. $this->request
  370. ->expects($this->once())
  371. ->method('passesCSRFCheck')
  372. ->willReturn(true);
  373. $this->throttler
  374. ->expects($this->once())
  375. ->method('sleepDelay')
  376. ->with('192.168.0.1');
  377. $this->throttler
  378. ->expects($this->once())
  379. ->method('getDelay')
  380. ->with('192.168.0.1')
  381. ->willReturn(200);
  382. $this->userManager->expects($this->once())
  383. ->method('checkPassword')
  384. ->will($this->returnValue($user));
  385. $this->userSession->expects($this->once())
  386. ->method('login')
  387. ->with($user, $password);
  388. $this->userSession->expects($this->once())
  389. ->method('createSessionToken')
  390. ->with($this->request, $user->getUID(), $user, $password, true);
  391. $this->twoFactorManager->expects($this->once())
  392. ->method('isTwoFactorAuthenticated')
  393. ->with($user)
  394. ->will($this->returnValue(false));
  395. $this->config->expects($this->once())
  396. ->method('deleteUserValue')
  397. ->with('uid', 'core', 'lostpassword');
  398. $this->userSession->expects($this->once())
  399. ->method('createRememberMeToken')
  400. ->with($user);
  401. $expected = new \OCP\AppFramework\Http\RedirectResponse($indexPageUrl);
  402. $this->assertEquals($expected, $this->loginController->tryLogin($user, $password, null, true));
  403. }
  404. public function testLoginWithoutPassedCsrfCheckAndNotLoggedIn() {
  405. /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */
  406. $user = $this->getMockBuilder('\OCP\IUser')->getMock();
  407. $user->expects($this->any())
  408. ->method('getUID')
  409. ->will($this->returnValue('jane'));
  410. $password = 'secret';
  411. $originalUrl = 'another%20url';
  412. $this->request
  413. ->expects($this->exactly(2))
  414. ->method('getRemoteAddress')
  415. ->willReturn('192.168.0.1');
  416. $this->request
  417. ->expects($this->once())
  418. ->method('passesCSRFCheck')
  419. ->willReturn(false);
  420. $this->throttler
  421. ->expects($this->once())
  422. ->method('sleepDelay')
  423. ->with('192.168.0.1');
  424. $this->throttler
  425. ->expects($this->once())
  426. ->method('getDelay')
  427. ->with('192.168.0.1')
  428. ->willReturn(200);
  429. $this->userSession->expects($this->once())
  430. ->method('isLoggedIn')
  431. ->with()
  432. ->will($this->returnValue(false));
  433. $this->config->expects($this->never())
  434. ->method('deleteUserValue');
  435. $this->userSession->expects($this->never())
  436. ->method('createRememberMeToken');
  437. $expected = new \OCP\AppFramework\Http\RedirectResponse(\OC_Util::getDefaultPageUrl());
  438. $this->assertEquals($expected, $this->loginController->tryLogin('Jane', $password, $originalUrl));
  439. }
  440. public function testLoginWithoutPassedCsrfCheckAndLoggedIn() {
  441. /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */
  442. $user = $this->getMockBuilder('\OCP\IUser')->getMock();
  443. $user->expects($this->any())
  444. ->method('getUID')
  445. ->will($this->returnValue('jane'));
  446. $password = 'secret';
  447. $originalUrl = 'another%20url';
  448. $redirectUrl = 'http://localhost/another url';
  449. $this->request
  450. ->expects($this->exactly(2))
  451. ->method('getRemoteAddress')
  452. ->willReturn('192.168.0.1');
  453. $this->request
  454. ->expects($this->once())
  455. ->method('passesCSRFCheck')
  456. ->willReturn(false);
  457. $this->throttler
  458. ->expects($this->once())
  459. ->method('sleepDelay')
  460. ->with('192.168.0.1');
  461. $this->throttler
  462. ->expects($this->once())
  463. ->method('getDelay')
  464. ->with('192.168.0.1')
  465. ->willReturn(200);
  466. $this->userSession->expects($this->once())
  467. ->method('isLoggedIn')
  468. ->with()
  469. ->will($this->returnValue(true));
  470. $this->urlGenerator->expects($this->once())
  471. ->method('getAbsoluteURL')
  472. ->with(urldecode($originalUrl))
  473. ->will($this->returnValue($redirectUrl));
  474. $this->config->expects($this->never())
  475. ->method('deleteUserValue');
  476. $this->userSession->expects($this->never())
  477. ->method('createRememberMeToken');
  478. $expected = new \OCP\AppFramework\Http\RedirectResponse($redirectUrl);
  479. $this->assertEquals($expected, $this->loginController->tryLogin('Jane', $password, $originalUrl));
  480. }
  481. public function testLoginWithValidCredentialsAndRedirectUrl() {
  482. /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */
  483. $user = $this->getMockBuilder('\OCP\IUser')->getMock();
  484. $user->expects($this->any())
  485. ->method('getUID')
  486. ->will($this->returnValue('jane'));
  487. $password = 'secret';
  488. $originalUrl = 'another%20url';
  489. $redirectUrl = 'http://localhost/another url';
  490. $this->request
  491. ->expects($this->exactly(2))
  492. ->method('getRemoteAddress')
  493. ->willReturn('192.168.0.1');
  494. $this->request
  495. ->expects($this->once())
  496. ->method('passesCSRFCheck')
  497. ->willReturn(true);
  498. $this->throttler
  499. ->expects($this->once())
  500. ->method('sleepDelay')
  501. ->with('192.168.0.1');
  502. $this->throttler
  503. ->expects($this->once())
  504. ->method('getDelay')
  505. ->with('192.168.0.1')
  506. ->willReturn(200);
  507. $this->userManager->expects($this->once())
  508. ->method('checkPassword')
  509. ->with('Jane', $password)
  510. ->will($this->returnValue($user));
  511. $this->userSession->expects($this->once())
  512. ->method('createSessionToken')
  513. ->with($this->request, $user->getUID(), 'Jane', $password, false);
  514. $this->userSession->expects($this->once())
  515. ->method('isLoggedIn')
  516. ->with()
  517. ->will($this->returnValue(true));
  518. $this->urlGenerator->expects($this->once())
  519. ->method('getAbsoluteURL')
  520. ->with(urldecode($originalUrl))
  521. ->will($this->returnValue($redirectUrl));
  522. $this->config->expects($this->once())
  523. ->method('deleteUserValue')
  524. ->with('jane', 'core', 'lostpassword');
  525. $expected = new \OCP\AppFramework\Http\RedirectResponse(urldecode($redirectUrl));
  526. $this->assertEquals($expected, $this->loginController->tryLogin('Jane', $password, $originalUrl));
  527. }
  528. public function testLoginWithOneTwoFactorProvider() {
  529. /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */
  530. $user = $this->getMockBuilder('\OCP\IUser')->getMock();
  531. $user->expects($this->any())
  532. ->method('getUID')
  533. ->will($this->returnValue('john'));
  534. $password = 'secret';
  535. $challengeUrl = 'challenge/url';
  536. $provider = $this->getMockBuilder('\OCP\Authentication\TwoFactorAuth\IProvider')->getMock();
  537. $this->request
  538. ->expects($this->exactly(2))
  539. ->method('getRemoteAddress')
  540. ->willReturn('192.168.0.1');
  541. $this->request
  542. ->expects($this->once())
  543. ->method('passesCSRFCheck')
  544. ->willReturn(true);
  545. $this->throttler
  546. ->expects($this->once())
  547. ->method('sleepDelay')
  548. ->with('192.168.0.1');
  549. $this->throttler
  550. ->expects($this->once())
  551. ->method('getDelay')
  552. ->with('192.168.0.1')
  553. ->willReturn(200);
  554. $this->userManager->expects($this->once())
  555. ->method('checkPassword')
  556. ->will($this->returnValue($user));
  557. $this->userSession->expects($this->once())
  558. ->method('login')
  559. ->with('john@doe.com', $password);
  560. $this->userSession->expects($this->once())
  561. ->method('createSessionToken')
  562. ->with($this->request, $user->getUID(), 'john@doe.com', $password, false);
  563. $this->twoFactorManager->expects($this->once())
  564. ->method('isTwoFactorAuthenticated')
  565. ->with($user)
  566. ->will($this->returnValue(true));
  567. $this->twoFactorManager->expects($this->once())
  568. ->method('prepareTwoFactorLogin')
  569. ->with($user);
  570. $this->twoFactorManager->expects($this->once())
  571. ->method('getProviders')
  572. ->with($user)
  573. ->will($this->returnValue([$provider]));
  574. $provider->expects($this->once())
  575. ->method('getId')
  576. ->will($this->returnValue('u2f'));
  577. $this->urlGenerator->expects($this->once())
  578. ->method('linkToRoute')
  579. ->with('core.TwoFactorChallenge.showChallenge', [
  580. 'challengeProviderId' => 'u2f',
  581. ])
  582. ->will($this->returnValue($challengeUrl));
  583. $this->config->expects($this->once())
  584. ->method('deleteUserValue')
  585. ->with('john', 'core', 'lostpassword');
  586. $this->userSession->expects($this->never())
  587. ->method('createRememberMeToken');
  588. $expected = new RedirectResponse($challengeUrl);
  589. $this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', $password, null));
  590. }
  591. public function testLoginWithMultpleTwoFactorProviders() {
  592. /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */
  593. $user = $this->getMockBuilder('\OCP\IUser')->getMock();
  594. $user->expects($this->any())
  595. ->method('getUID')
  596. ->will($this->returnValue('john'));
  597. $password = 'secret';
  598. $challengeUrl = 'challenge/url';
  599. $provider1 = $this->getMockBuilder('\OCP\Authentication\TwoFactorAuth\IProvider')->getMock();
  600. $provider2 = $this->getMockBuilder('\OCP\Authentication\TwoFactorAuth\IProvider')->getMock();
  601. $this->request
  602. ->expects($this->exactly(2))
  603. ->method('getRemoteAddress')
  604. ->willReturn('192.168.0.1');
  605. $this->request
  606. ->expects($this->once())
  607. ->method('passesCSRFCheck')
  608. ->willReturn(true);
  609. $this->throttler
  610. ->expects($this->once())
  611. ->method('sleepDelay')
  612. ->with('192.168.0.1');
  613. $this->throttler
  614. ->expects($this->once())
  615. ->method('getDelay')
  616. ->with('192.168.0.1')
  617. ->willReturn(200);
  618. $this->userManager->expects($this->once())
  619. ->method('checkPassword')
  620. ->will($this->returnValue($user));
  621. $this->userSession->expects($this->once())
  622. ->method('login')
  623. ->with('john@doe.com', $password);
  624. $this->userSession->expects($this->once())
  625. ->method('createSessionToken')
  626. ->with($this->request, $user->getUID(), 'john@doe.com', $password, false);
  627. $this->twoFactorManager->expects($this->once())
  628. ->method('isTwoFactorAuthenticated')
  629. ->with($user)
  630. ->will($this->returnValue(true));
  631. $this->twoFactorManager->expects($this->once())
  632. ->method('prepareTwoFactorLogin')
  633. ->with($user);
  634. $this->twoFactorManager->expects($this->once())
  635. ->method('getProviders')
  636. ->with($user)
  637. ->will($this->returnValue([$provider1, $provider2]));
  638. $provider1->expects($this->never())
  639. ->method('getId');
  640. $provider2->expects($this->never())
  641. ->method('getId');
  642. $this->urlGenerator->expects($this->once())
  643. ->method('linkToRoute')
  644. ->with('core.TwoFactorChallenge.selectChallenge')
  645. ->will($this->returnValue($challengeUrl));
  646. $this->config->expects($this->once())
  647. ->method('deleteUserValue')
  648. ->with('john', 'core', 'lostpassword');
  649. $this->userSession->expects($this->never())
  650. ->method('createRememberMeToken');
  651. $expected = new RedirectResponse($challengeUrl);
  652. $this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', $password, null));
  653. }
  654. public function testToNotLeakLoginName() {
  655. /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */
  656. $user = $this->getMockBuilder('\OCP\IUser')->getMock();
  657. $user->expects($this->any())
  658. ->method('getUID')
  659. ->will($this->returnValue('john'));
  660. $this->userManager->expects($this->exactly(2))
  661. ->method('checkPassword')
  662. ->withConsecutive(
  663. ['john@doe.com', 'just wrong'],
  664. ['john', 'just wrong']
  665. )
  666. ->willReturn(false);
  667. $this->userManager->expects($this->once())
  668. ->method('getByEmail')
  669. ->with('john@doe.com')
  670. ->willReturn([$user]);
  671. $this->urlGenerator->expects($this->once())
  672. ->method('linkToRoute')
  673. ->with('core.login.showLoginForm', ['user' => 'john@doe.com'])
  674. ->will($this->returnValue(''));
  675. $this->request
  676. ->expects($this->exactly(3))
  677. ->method('getRemoteAddress')
  678. ->willReturn('192.168.0.1');
  679. $this->request
  680. ->expects($this->once())
  681. ->method('passesCSRFCheck')
  682. ->willReturn(true);
  683. $this->throttler
  684. ->expects($this->once())
  685. ->method('getDelay')
  686. ->with('192.168.0.1')
  687. ->willReturn(200);
  688. $this->throttler
  689. ->expects($this->once())
  690. ->method('sleepDelay')
  691. ->with('192.168.0.1');
  692. $this->throttler
  693. ->expects($this->once())
  694. ->method('registerAttempt')
  695. ->with('login', '192.168.0.1', ['user' => 'john@doe.com']);
  696. $this->config->expects($this->never())
  697. ->method('deleteUserValue');
  698. $this->userSession->expects($this->never())
  699. ->method('createRememberMeToken');
  700. $expected = new RedirectResponse('');
  701. $this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', 'just wrong', null));
  702. }
  703. }