SessionTest.php 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286
  1. <?php
  2. /**
  3. * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. namespace Test\User;
  9. use OC\AppFramework\Http\Request;
  10. use OC\Authentication\Events\LoginFailed;
  11. use OC\Authentication\Exceptions\InvalidTokenException;
  12. use OC\Authentication\Exceptions\PasswordlessTokenException;
  13. use OC\Authentication\Exceptions\PasswordLoginForbiddenException;
  14. use OC\Authentication\Token\IProvider;
  15. use OC\Authentication\Token\IToken;
  16. use OC\Authentication\Token\PublicKeyToken;
  17. use OC\Security\CSRF\CsrfTokenManager;
  18. use OC\Session\Memory;
  19. use OC\User\LoginException;
  20. use OC\User\Manager;
  21. use OC\User\Session;
  22. use OC\User\User;
  23. use OCA\DAV\Connector\Sabre\Auth;
  24. use OCP\AppFramework\Utility\ITimeFactory;
  25. use OCP\EventDispatcher\IEventDispatcher;
  26. use OCP\ICacheFactory;
  27. use OCP\IConfig;
  28. use OCP\IRequest;
  29. use OCP\IRequestId;
  30. use OCP\ISession;
  31. use OCP\IUser;
  32. use OCP\Lockdown\ILockdownManager;
  33. use OCP\Security\Bruteforce\IThrottler;
  34. use OCP\Security\ISecureRandom;
  35. use OCP\User\Events\PostLoginEvent;
  36. use PHPUnit\Framework\MockObject\MockObject;
  37. use Psr\Log\LoggerInterface;
  38. use function array_diff;
  39. use function get_class_methods;
  40. /**
  41. * @group DB
  42. * @package Test\User
  43. */
  44. class SessionTest extends \Test\TestCase {
  45. /** @var ITimeFactory|MockObject */
  46. private $timeFactory;
  47. /** @var IProvider|MockObject */
  48. private $tokenProvider;
  49. /** @var IConfig|MockObject */
  50. private $config;
  51. /** @var IThrottler|MockObject */
  52. private $throttler;
  53. /** @var ISecureRandom|MockObject */
  54. private $random;
  55. /** @var Manager|MockObject */
  56. private $manager;
  57. /** @var ISession|MockObject */
  58. private $session;
  59. /** @var Session|MockObject */
  60. private $userSession;
  61. /** @var ILockdownManager|MockObject */
  62. private $lockdownManager;
  63. /** @var LoggerInterface|MockObject */
  64. private $logger;
  65. /** @var IEventDispatcher|MockObject */
  66. private $dispatcher;
  67. protected function setUp(): void {
  68. parent::setUp();
  69. $this->timeFactory = $this->createMock(ITimeFactory::class);
  70. $this->timeFactory->expects($this->any())
  71. ->method('getTime')
  72. ->willReturn(10000);
  73. $this->tokenProvider = $this->createMock(IProvider::class);
  74. $this->config = $this->createMock(IConfig::class);
  75. $this->throttler = $this->createMock(IThrottler::class);
  76. $this->random = $this->createMock(ISecureRandom::class);
  77. $this->manager = $this->createMock(Manager::class);
  78. $this->session = $this->createMock(ISession::class);
  79. $this->lockdownManager = $this->createMock(ILockdownManager::class);
  80. $this->logger = $this->createMock(LoggerInterface::class);
  81. $this->dispatcher = $this->createMock(IEventDispatcher::class);
  82. $this->userSession = $this->getMockBuilder(Session::class)
  83. ->setConstructorArgs([
  84. $this->manager,
  85. $this->session,
  86. $this->timeFactory,
  87. $this->tokenProvider,
  88. $this->config,
  89. $this->random,
  90. $this->lockdownManager,
  91. $this->logger,
  92. $this->dispatcher
  93. ])
  94. ->setMethods([
  95. 'setMagicInCookie',
  96. ])
  97. ->getMock();
  98. \OC_User::setIncognitoMode(false);
  99. }
  100. public function isLoggedInData() {
  101. return [
  102. [true],
  103. [false],
  104. ];
  105. }
  106. /**
  107. * @dataProvider isLoggedInData
  108. */
  109. public function testIsLoggedIn($isLoggedIn) {
  110. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  111. $manager = $this->createMock(Manager::class);
  112. $userSession = $this->getMockBuilder(Session::class)
  113. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  114. ->setMethods([
  115. 'getUser'
  116. ])
  117. ->getMock();
  118. $user = new User('sepp', null, $this->createMock(IEventDispatcher::class));
  119. $userSession->expects($this->once())
  120. ->method('getUser')
  121. ->willReturn($isLoggedIn ? $user : null);
  122. $this->assertEquals($isLoggedIn, $userSession->isLoggedIn());
  123. }
  124. public function testSetUser() {
  125. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  126. $session->expects($this->once())
  127. ->method('set')
  128. ->with('user_id', 'foo');
  129. $manager = $this->createMock(Manager::class);
  130. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  131. $user = $this->createMock(IUser::class);
  132. $user->expects($this->once())
  133. ->method('getUID')
  134. ->willReturn('foo');
  135. $userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
  136. $userSession->setUser($user);
  137. }
  138. public function testLoginValidPasswordEnabled() {
  139. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  140. $session->expects($this->once())
  141. ->method('regenerateId');
  142. $this->tokenProvider->expects($this->once())
  143. ->method('getToken')
  144. ->with('bar')
  145. ->will($this->throwException(new InvalidTokenException()));
  146. $session->expects($this->exactly(2))
  147. ->method('set')
  148. ->with($this->callback(function ($key) {
  149. switch ($key) {
  150. case 'user_id':
  151. case 'loginname':
  152. return true;
  153. break;
  154. default:
  155. return false;
  156. break;
  157. }
  158. }, 'foo'));
  159. $managerMethods = get_class_methods(Manager::class);
  160. //keep following methods intact in order to ensure hooks are working
  161. $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
  162. $manager = $this->getMockBuilder(Manager::class)
  163. ->setMethods($mockedManagerMethods)
  164. ->setConstructorArgs([
  165. $this->config,
  166. $this->createMock(ICacheFactory::class),
  167. $this->createMock(IEventDispatcher::class),
  168. $this->createMock(LoggerInterface::class),
  169. ])
  170. ->getMock();
  171. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  172. $user = $this->createMock(IUser::class);
  173. $user->expects($this->any())
  174. ->method('isEnabled')
  175. ->willReturn(true);
  176. $user->expects($this->any())
  177. ->method('getUID')
  178. ->willReturn('foo');
  179. $user->expects($this->once())
  180. ->method('updateLastLoginTimestamp');
  181. $manager->expects($this->once())
  182. ->method('checkPasswordNoLogging')
  183. ->with('foo', 'bar')
  184. ->willReturn($user);
  185. $userSession = $this->getMockBuilder(Session::class)
  186. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  187. ->setMethods([
  188. 'prepareUserLogin'
  189. ])
  190. ->getMock();
  191. $userSession->expects($this->once())
  192. ->method('prepareUserLogin');
  193. $this->dispatcher->expects($this->once())
  194. ->method('dispatchTyped')
  195. ->with(
  196. $this->callback(function (PostLoginEvent $e) {
  197. return $e->getUser()->getUID() === 'foo' &&
  198. $e->getPassword() === 'bar' &&
  199. $e->isTokenLogin() === false;
  200. })
  201. );
  202. $userSession->login('foo', 'bar');
  203. $this->assertEquals($user, $userSession->getUser());
  204. }
  205. public function testLoginValidPasswordDisabled() {
  206. $this->expectException(LoginException::class);
  207. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  208. $session->expects($this->never())
  209. ->method('set');
  210. $session->expects($this->once())
  211. ->method('regenerateId');
  212. $this->tokenProvider->expects($this->once())
  213. ->method('getToken')
  214. ->with('bar')
  215. ->will($this->throwException(new InvalidTokenException()));
  216. $managerMethods = get_class_methods(Manager::class);
  217. //keep following methods intact in order to ensure hooks are working
  218. $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
  219. $manager = $this->getMockBuilder(Manager::class)
  220. ->setMethods($mockedManagerMethods)
  221. ->setConstructorArgs([
  222. $this->config,
  223. $this->createMock(ICacheFactory::class),
  224. $this->createMock(IEventDispatcher::class),
  225. $this->createMock(LoggerInterface::class),
  226. ])
  227. ->getMock();
  228. $user = $this->createMock(IUser::class);
  229. $user->expects($this->any())
  230. ->method('isEnabled')
  231. ->willReturn(false);
  232. $user->expects($this->never())
  233. ->method('updateLastLoginTimestamp');
  234. $manager->expects($this->once())
  235. ->method('checkPasswordNoLogging')
  236. ->with('foo', 'bar')
  237. ->willReturn($user);
  238. $this->dispatcher->expects($this->never())
  239. ->method('dispatch');
  240. $userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
  241. $userSession->login('foo', 'bar');
  242. }
  243. public function testLoginInvalidPassword() {
  244. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  245. $managerMethods = get_class_methods(Manager::class);
  246. //keep following methods intact in order to ensure hooks are working
  247. $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
  248. $manager = $this->getMockBuilder(Manager::class)
  249. ->setMethods($mockedManagerMethods)
  250. ->setConstructorArgs([
  251. $this->config,
  252. $this->createMock(ICacheFactory::class),
  253. $this->createMock(IEventDispatcher::class),
  254. $this->createMock(LoggerInterface::class),
  255. ])
  256. ->getMock();
  257. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  258. $userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
  259. $user = $this->createMock(IUser::class);
  260. $session->expects($this->never())
  261. ->method('set');
  262. $session->expects($this->once())
  263. ->method('regenerateId');
  264. $this->tokenProvider->expects($this->once())
  265. ->method('getToken')
  266. ->with('bar')
  267. ->will($this->throwException(new InvalidTokenException()));
  268. $user->expects($this->never())
  269. ->method('isEnabled');
  270. $user->expects($this->never())
  271. ->method('updateLastLoginTimestamp');
  272. $manager->expects($this->once())
  273. ->method('checkPasswordNoLogging')
  274. ->with('foo', 'bar')
  275. ->willReturn(false);
  276. $this->dispatcher->expects($this->never())
  277. ->method('dispatch');
  278. $userSession->login('foo', 'bar');
  279. }
  280. public function testPasswordlessLoginNoLastCheckUpdate(): void {
  281. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  282. $managerMethods = get_class_methods(Manager::class);
  283. // Keep following methods intact in order to ensure hooks are working
  284. $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
  285. $manager = $this->getMockBuilder(Manager::class)
  286. ->setMethods($mockedManagerMethods)
  287. ->setConstructorArgs([
  288. $this->config,
  289. $this->createMock(ICacheFactory::class),
  290. $this->createMock(IEventDispatcher::class),
  291. $this->createMock(LoggerInterface::class),
  292. ])
  293. ->getMock();
  294. $userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
  295. $session->expects($this->never())
  296. ->method('set');
  297. $session->expects($this->once())
  298. ->method('regenerateId');
  299. $token = new PublicKeyToken();
  300. $token->setLoginName('foo');
  301. $token->setLastCheck(0); // Never
  302. $token->setUid('foo');
  303. $this->tokenProvider
  304. ->method('getPassword')
  305. ->with($token)
  306. ->willThrowException(new PasswordlessTokenException());
  307. $this->tokenProvider
  308. ->method('getToken')
  309. ->with('app-password')
  310. ->willReturn($token);
  311. $this->tokenProvider->expects(self::never())
  312. ->method('updateToken');
  313. $userSession->login('foo', 'app-password');
  314. }
  315. public function testLoginLastCheckUpdate(): void {
  316. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  317. $managerMethods = get_class_methods(Manager::class);
  318. // Keep following methods intact in order to ensure hooks are working
  319. $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
  320. $manager = $this->getMockBuilder(Manager::class)
  321. ->setMethods($mockedManagerMethods)
  322. ->setConstructorArgs([
  323. $this->config,
  324. $this->createMock(ICacheFactory::class),
  325. $this->createMock(IEventDispatcher::class),
  326. $this->createMock(LoggerInterface::class),
  327. ])
  328. ->getMock();
  329. $userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
  330. $session->expects($this->never())
  331. ->method('set');
  332. $session->expects($this->once())
  333. ->method('regenerateId');
  334. $token = new PublicKeyToken();
  335. $token->setLoginName('foo');
  336. $token->setLastCheck(0); // Never
  337. $token->setUid('foo');
  338. $this->tokenProvider
  339. ->method('getPassword')
  340. ->with($token)
  341. ->willReturn('secret');
  342. $this->tokenProvider
  343. ->method('getToken')
  344. ->with('app-password')
  345. ->willReturn($token);
  346. $this->tokenProvider->expects(self::once())
  347. ->method('updateToken');
  348. $userSession->login('foo', 'app-password');
  349. }
  350. public function testLoginNonExisting() {
  351. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  352. $manager = $this->createMock(Manager::class);
  353. $userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
  354. $session->expects($this->never())
  355. ->method('set');
  356. $session->expects($this->once())
  357. ->method('regenerateId');
  358. $this->tokenProvider->expects($this->once())
  359. ->method('getToken')
  360. ->with('bar')
  361. ->will($this->throwException(new InvalidTokenException()));
  362. $manager->expects($this->once())
  363. ->method('checkPasswordNoLogging')
  364. ->with('foo', 'bar')
  365. ->willReturn(false);
  366. $userSession->login('foo', 'bar');
  367. }
  368. public function testLogClientInNoTokenPasswordWith2fa() {
  369. $this->expectException(PasswordLoginForbiddenException::class);
  370. $manager = $this->createMock(Manager::class);
  371. $session = $this->createMock(ISession::class);
  372. $request = $this->createMock(IRequest::class);
  373. /** @var Session $userSession */
  374. $userSession = $this->getMockBuilder(Session::class)
  375. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  376. ->setMethods(['login', 'supportsCookies', 'createSessionToken', 'getUser'])
  377. ->getMock();
  378. $this->tokenProvider->expects($this->once())
  379. ->method('getToken')
  380. ->with('doe')
  381. ->will($this->throwException(new InvalidTokenException()));
  382. $this->config->expects($this->once())
  383. ->method('getSystemValueBool')
  384. ->with('token_auth_enforced', false)
  385. ->willReturn(true);
  386. $request
  387. ->expects($this->any())
  388. ->method('getRemoteAddress')
  389. ->willReturn('192.168.0.1');
  390. $this->throttler
  391. ->expects($this->once())
  392. ->method('sleepDelayOrThrowOnMax')
  393. ->with('192.168.0.1');
  394. $this->throttler
  395. ->expects($this->any())
  396. ->method('getDelay')
  397. ->with('192.168.0.1')
  398. ->willReturn(0);
  399. $userSession->logClientIn('john', 'doe', $request, $this->throttler);
  400. }
  401. public function testLogClientInUnexist() {
  402. $manager = $this->createMock(Manager::class);
  403. $session = $this->createMock(ISession::class);
  404. $request = $this->createMock(IRequest::class);
  405. /** @var Session $userSession */
  406. $userSession = $this->getMockBuilder(Session::class)
  407. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  408. ->setMethods(['login', 'supportsCookies', 'createSessionToken', 'getUser'])
  409. ->getMock();
  410. $this->tokenProvider->expects($this->once())
  411. ->method('getToken')
  412. ->with('doe')
  413. ->will($this->throwException(new InvalidTokenException()));
  414. $this->config->expects($this->once())
  415. ->method('getSystemValueBool')
  416. ->with('token_auth_enforced', false)
  417. ->willReturn(false);
  418. $manager->method('getByEmail')
  419. ->with('unexist')
  420. ->willReturn([]);
  421. $this->assertFalse($userSession->logClientIn('unexist', 'doe', $request, $this->throttler));
  422. }
  423. public function testLogClientInWithTokenPassword() {
  424. $manager = $this->createMock(Manager::class);
  425. $session = $this->createMock(ISession::class);
  426. $request = $this->createMock(IRequest::class);
  427. /** @var Session $userSession */
  428. $userSession = $this->getMockBuilder(Session::class)
  429. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  430. ->setMethods(['isTokenPassword', 'login', 'supportsCookies', 'createSessionToken', 'getUser'])
  431. ->getMock();
  432. $userSession->expects($this->once())
  433. ->method('isTokenPassword')
  434. ->willReturn(true);
  435. $userSession->expects($this->once())
  436. ->method('login')
  437. ->with('john', 'I-AM-AN-APP-PASSWORD')
  438. ->willReturn(true);
  439. $session->expects($this->once())
  440. ->method('set')
  441. ->with('app_password', 'I-AM-AN-APP-PASSWORD');
  442. $request
  443. ->expects($this->any())
  444. ->method('getRemoteAddress')
  445. ->willReturn('192.168.0.1');
  446. $this->throttler
  447. ->expects($this->once())
  448. ->method('sleepDelayOrThrowOnMax')
  449. ->with('192.168.0.1');
  450. $this->throttler
  451. ->expects($this->any())
  452. ->method('getDelay')
  453. ->with('192.168.0.1')
  454. ->willReturn(0);
  455. $this->assertTrue($userSession->logClientIn('john', 'I-AM-AN-APP-PASSWORD', $request, $this->throttler));
  456. }
  457. public function testLogClientInNoTokenPasswordNo2fa() {
  458. $this->expectException(PasswordLoginForbiddenException::class);
  459. $manager = $this->createMock(Manager::class);
  460. $session = $this->createMock(ISession::class);
  461. $request = $this->createMock(IRequest::class);
  462. /** @var Session $userSession */
  463. $userSession = $this->getMockBuilder(Session::class)
  464. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  465. ->setMethods(['login', 'isTwoFactorEnforced'])
  466. ->getMock();
  467. $this->tokenProvider->expects($this->once())
  468. ->method('getToken')
  469. ->with('doe')
  470. ->will($this->throwException(new InvalidTokenException()));
  471. $this->config->expects($this->once())
  472. ->method('getSystemValueBool')
  473. ->with('token_auth_enforced', false)
  474. ->willReturn(false);
  475. $userSession->expects($this->once())
  476. ->method('isTwoFactorEnforced')
  477. ->with('john')
  478. ->willReturn(true);
  479. $request
  480. ->expects($this->any())
  481. ->method('getRemoteAddress')
  482. ->willReturn('192.168.0.1');
  483. $this->throttler
  484. ->expects($this->once())
  485. ->method('sleepDelayOrThrowOnMax')
  486. ->with('192.168.0.1');
  487. $this->throttler
  488. ->expects($this->any())
  489. ->method('getDelay')
  490. ->with('192.168.0.1')
  491. ->willReturn(0);
  492. $userSession->logClientIn('john', 'doe', $request, $this->throttler);
  493. }
  494. public function testTryTokenLoginNoHeaderNoSessionCookie(): void {
  495. $request = $this->createMock(IRequest::class);
  496. $this->config->expects(self::once())
  497. ->method('getSystemValueString')
  498. ->with('instanceid')
  499. ->willReturn('abc123');
  500. $request->method('getHeader')->with('Authorization')->willReturn('');
  501. $request->method('getCookie')->with('abc123')->willReturn(null);
  502. $this->tokenProvider->expects(self::never())
  503. ->method('getToken');
  504. $loginResult = $this->userSession->tryTokenLogin($request);
  505. self::assertFalse($loginResult);
  506. }
  507. public function testTryTokenLoginAuthorizationHeaderTokenNotFound(): void {
  508. $request = $this->createMock(IRequest::class);
  509. $request->method('getHeader')->with('Authorization')->willReturn('Bearer abcde-12345');
  510. $this->tokenProvider->expects(self::once())
  511. ->method('getToken')
  512. ->with('abcde-12345')
  513. ->willThrowException(new InvalidTokenException());
  514. $loginResult = $this->userSession->tryTokenLogin($request);
  515. self::assertFalse($loginResult);
  516. }
  517. public function testTryTokenLoginSessionIdTokenNotFound(): void {
  518. $request = $this->createMock(IRequest::class);
  519. $this->config->expects(self::once())
  520. ->method('getSystemValueString')
  521. ->with('instanceid')
  522. ->willReturn('abc123');
  523. $request->method('getHeader')->with('Authorization')->willReturn('');
  524. $request->method('getCookie')->with('abc123')->willReturn('abcde12345');
  525. $this->session->expects(self::once())
  526. ->method('getId')
  527. ->willReturn('abcde12345');
  528. $this->tokenProvider->expects(self::once())
  529. ->method('getToken')
  530. ->with('abcde12345')
  531. ->willThrowException(new InvalidTokenException());
  532. $loginResult = $this->userSession->tryTokenLogin($request);
  533. self::assertFalse($loginResult);
  534. }
  535. public function testRememberLoginValidToken() {
  536. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  537. $managerMethods = get_class_methods(Manager::class);
  538. //keep following methods intact in order to ensure hooks are working
  539. $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
  540. $manager = $this->getMockBuilder(Manager::class)
  541. ->setMethods($mockedManagerMethods)
  542. ->setConstructorArgs([
  543. $this->config,
  544. $this->createMock(ICacheFactory::class),
  545. $this->createMock(IEventDispatcher::class),
  546. $this->createMock(LoggerInterface::class),
  547. ])
  548. ->getMock();
  549. $userSession = $this->getMockBuilder(Session::class)
  550. //override, otherwise tests will fail because of setcookie()
  551. ->setMethods(['setMagicInCookie', 'setLoginName'])
  552. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  553. ->getMock();
  554. $user = $this->createMock(IUser::class);
  555. $token = 'goodToken';
  556. $oldSessionId = 'sess321';
  557. $sessionId = 'sess123';
  558. $session->expects($this->once())
  559. ->method('regenerateId');
  560. $manager->expects($this->once())
  561. ->method('get')
  562. ->with('foo')
  563. ->willReturn($user);
  564. $this->config->expects($this->once())
  565. ->method('getUserKeys')
  566. ->with('foo', 'login_token')
  567. ->willReturn([$token]);
  568. $this->config->expects($this->once())
  569. ->method('deleteUserValue')
  570. ->with('foo', 'login_token', $token);
  571. $this->random->expects($this->once())
  572. ->method('generate')
  573. ->with(32)
  574. ->willReturn('abcdefg123456');
  575. $this->config->expects($this->once())
  576. ->method('setUserValue')
  577. ->with('foo', 'login_token', 'abcdefg123456', 10000);
  578. $tokenObject = $this->createMock(IToken::class);
  579. $tokenObject->expects($this->once())
  580. ->method('getLoginName')
  581. ->willReturn('foobar');
  582. $tokenObject->method('getId')
  583. ->willReturn(42);
  584. $session->expects($this->once())
  585. ->method('getId')
  586. ->willReturn($sessionId);
  587. $this->tokenProvider->expects($this->once())
  588. ->method('renewSessionToken')
  589. ->with($oldSessionId, $sessionId)
  590. ->willReturn($tokenObject);
  591. $this->tokenProvider->expects($this->never())
  592. ->method('getToken');
  593. $user->expects($this->any())
  594. ->method('getUID')
  595. ->willReturn('foo');
  596. $userSession->expects($this->once())
  597. ->method('setMagicInCookie');
  598. $user->expects($this->once())
  599. ->method('updateLastLoginTimestamp');
  600. $setUID = false;
  601. $session
  602. ->method('set')
  603. ->willReturnCallback(function ($k, $v) use (&$setUID) {
  604. if ($k === 'user_id' && $v === 'foo') {
  605. $setUID = true;
  606. }
  607. });
  608. $userSession->expects($this->once())
  609. ->method('setLoginName')
  610. ->willReturn('foobar');
  611. $granted = $userSession->loginWithCookie('foo', $token, $oldSessionId);
  612. $this->assertTrue($setUID);
  613. $this->assertTrue($granted);
  614. }
  615. public function testRememberLoginInvalidSessionToken() {
  616. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  617. $managerMethods = get_class_methods(Manager::class);
  618. //keep following methods intact in order to ensure hooks are working
  619. $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
  620. $manager = $this->getMockBuilder(Manager::class)
  621. ->setMethods($mockedManagerMethods)
  622. ->setConstructorArgs([
  623. $this->config,
  624. $this->createMock(ICacheFactory::class),
  625. $this->createMock(IEventDispatcher::class),
  626. $this->createMock(LoggerInterface::class),
  627. ])
  628. ->getMock();
  629. $userSession = $this->getMockBuilder(Session::class)
  630. //override, otherwise tests will fail because of setcookie()
  631. ->setMethods(['setMagicInCookie'])
  632. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  633. ->getMock();
  634. $user = $this->createMock(IUser::class);
  635. $token = 'goodToken';
  636. $oldSessionId = 'sess321';
  637. $sessionId = 'sess123';
  638. $session->expects($this->once())
  639. ->method('regenerateId');
  640. $manager->expects($this->once())
  641. ->method('get')
  642. ->with('foo')
  643. ->willReturn($user);
  644. $this->config->expects($this->once())
  645. ->method('getUserKeys')
  646. ->with('foo', 'login_token')
  647. ->willReturn([$token]);
  648. $this->config->expects($this->once())
  649. ->method('deleteUserValue')
  650. ->with('foo', 'login_token', $token);
  651. $this->config->expects($this->once())
  652. ->method('setUserValue'); // TODO: mock new random value
  653. $session->expects($this->once())
  654. ->method('getId')
  655. ->willReturn($sessionId);
  656. $this->tokenProvider->expects($this->once())
  657. ->method('renewSessionToken')
  658. ->with($oldSessionId, $sessionId)
  659. ->will($this->throwException(new InvalidTokenException()));
  660. $user->expects($this->never())
  661. ->method('getUID')
  662. ->willReturn('foo');
  663. $userSession->expects($this->never())
  664. ->method('setMagicInCookie');
  665. $user->expects($this->never())
  666. ->method('updateLastLoginTimestamp');
  667. $session->expects($this->never())
  668. ->method('set')
  669. ->with('user_id', 'foo');
  670. $granted = $userSession->loginWithCookie('foo', $token, $oldSessionId);
  671. $this->assertFalse($granted);
  672. }
  673. public function testRememberLoginInvalidToken() {
  674. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  675. $managerMethods = get_class_methods(Manager::class);
  676. //keep following methods intact in order to ensure hooks are working
  677. $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
  678. $manager = $this->getMockBuilder(Manager::class)
  679. ->setMethods($mockedManagerMethods)
  680. ->setConstructorArgs([
  681. $this->config,
  682. $this->createMock(ICacheFactory::class),
  683. $this->createMock(IEventDispatcher::class),
  684. $this->createMock(LoggerInterface::class),
  685. ])
  686. ->getMock();
  687. $userSession = $this->getMockBuilder(Session::class)
  688. //override, otherwise tests will fail because of setcookie()
  689. ->setMethods(['setMagicInCookie'])
  690. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  691. ->getMock();
  692. $user = $this->createMock(IUser::class);
  693. $token = 'goodToken';
  694. $oldSessionId = 'sess321';
  695. $session->expects($this->once())
  696. ->method('regenerateId');
  697. $manager->expects($this->once())
  698. ->method('get')
  699. ->with('foo')
  700. ->willReturn($user);
  701. $this->config->expects($this->once())
  702. ->method('getUserKeys')
  703. ->with('foo', 'login_token')
  704. ->willReturn(['anothertoken']);
  705. $this->config->expects($this->never())
  706. ->method('deleteUserValue')
  707. ->with('foo', 'login_token', $token);
  708. $this->tokenProvider->expects($this->never())
  709. ->method('renewSessionToken');
  710. $userSession->expects($this->never())
  711. ->method('setMagicInCookie');
  712. $user->expects($this->never())
  713. ->method('updateLastLoginTimestamp');
  714. $session->expects($this->never())
  715. ->method('set')
  716. ->with('user_id', 'foo');
  717. $granted = $userSession->loginWithCookie('foo', $token, $oldSessionId);
  718. $this->assertFalse($granted);
  719. }
  720. public function testRememberLoginInvalidUser() {
  721. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  722. $managerMethods = get_class_methods(Manager::class);
  723. //keep following methods intact in order to ensure hooks are working
  724. $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
  725. $manager = $this->getMockBuilder(Manager::class)
  726. ->setMethods($mockedManagerMethods)
  727. ->setConstructorArgs([
  728. $this->config,
  729. $this->createMock(ICacheFactory::class),
  730. $this->createMock(IEventDispatcher::class),
  731. $this->createMock(LoggerInterface::class),
  732. ])
  733. ->getMock();
  734. $userSession = $this->getMockBuilder(Session::class)
  735. //override, otherwise tests will fail because of setcookie()
  736. ->setMethods(['setMagicInCookie'])
  737. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  738. ->getMock();
  739. $token = 'goodToken';
  740. $oldSessionId = 'sess321';
  741. $session->expects($this->once())
  742. ->method('regenerateId');
  743. $manager->expects($this->once())
  744. ->method('get')
  745. ->with('foo')
  746. ->willReturn(null);
  747. $this->config->expects($this->never())
  748. ->method('getUserKeys')
  749. ->with('foo', 'login_token')
  750. ->willReturn(['anothertoken']);
  751. $this->tokenProvider->expects($this->never())
  752. ->method('renewSessionToken');
  753. $userSession->expects($this->never())
  754. ->method('setMagicInCookie');
  755. $session->expects($this->never())
  756. ->method('set')
  757. ->with('user_id', 'foo');
  758. $granted = $userSession->loginWithCookie('foo', $token, $oldSessionId);
  759. $this->assertFalse($granted);
  760. }
  761. public function testActiveUserAfterSetSession() {
  762. $users = [
  763. 'foo' => new User('foo', null, $this->createMock(IEventDispatcher::class)),
  764. 'bar' => new User('bar', null, $this->createMock(IEventDispatcher::class))
  765. ];
  766. $manager = $this->getMockBuilder(Manager::class)
  767. ->disableOriginalConstructor()
  768. ->getMock();
  769. $manager->expects($this->any())
  770. ->method('get')
  771. ->willReturnCallback(function ($uid) use ($users) {
  772. return $users[$uid];
  773. });
  774. $session = new Memory('');
  775. $session->set('user_id', 'foo');
  776. $userSession = $this->getMockBuilder(Session::class)
  777. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  778. ->setMethods([
  779. 'validateSession'
  780. ])
  781. ->getMock();
  782. $userSession->expects($this->any())
  783. ->method('validateSession');
  784. $this->assertEquals($users['foo'], $userSession->getUser());
  785. $session2 = new Memory('');
  786. $session2->set('user_id', 'bar');
  787. $userSession->setSession($session2);
  788. $this->assertEquals($users['bar'], $userSession->getUser());
  789. }
  790. public function testCreateSessionToken() {
  791. $manager = $this->createMock(Manager::class);
  792. $session = $this->createMock(ISession::class);
  793. $user = $this->createMock(IUser::class);
  794. $userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
  795. $requestId = $this->createMock(IRequestId::class);
  796. $config = $this->createMock(IConfig::class);
  797. $csrf = $this->getMockBuilder(CsrfTokenManager::class)
  798. ->disableOriginalConstructor()
  799. ->getMock();
  800. $request = new Request([
  801. 'server' => [
  802. 'HTTP_USER_AGENT' => 'Firefox',
  803. ]
  804. ], $requestId, $config, $csrf);
  805. $uid = 'user123';
  806. $loginName = 'User123';
  807. $password = 'passme';
  808. $sessionId = 'abcxyz';
  809. $manager->expects($this->once())
  810. ->method('get')
  811. ->with($uid)
  812. ->willReturn($user);
  813. $session->expects($this->once())
  814. ->method('getId')
  815. ->willReturn($sessionId);
  816. $this->tokenProvider->expects($this->once())
  817. ->method('getToken')
  818. ->with($password)
  819. ->will($this->throwException(new InvalidTokenException()));
  820. $this->tokenProvider->expects($this->once())
  821. ->method('generateToken')
  822. ->with($sessionId, $uid, $loginName, $password, 'Firefox', IToken::TEMPORARY_TOKEN, IToken::DO_NOT_REMEMBER);
  823. $this->assertTrue($userSession->createSessionToken($request, $uid, $loginName, $password));
  824. }
  825. public function testCreateRememberedSessionToken() {
  826. $manager = $this->createMock(Manager::class);
  827. $session = $this->createMock(ISession::class);
  828. $user = $this->createMock(IUser::class);
  829. $userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
  830. $requestId = $this->createMock(IRequestId::class);
  831. $config = $this->createMock(IConfig::class);
  832. $csrf = $this->getMockBuilder(CsrfTokenManager::class)
  833. ->disableOriginalConstructor()
  834. ->getMock();
  835. $request = new Request([
  836. 'server' => [
  837. 'HTTP_USER_AGENT' => 'Firefox',
  838. ]
  839. ], $requestId, $config, $csrf);
  840. $uid = 'user123';
  841. $loginName = 'User123';
  842. $password = 'passme';
  843. $sessionId = 'abcxyz';
  844. $manager->expects($this->once())
  845. ->method('get')
  846. ->with($uid)
  847. ->willReturn($user);
  848. $session->expects($this->once())
  849. ->method('getId')
  850. ->willReturn($sessionId);
  851. $this->tokenProvider->expects($this->once())
  852. ->method('getToken')
  853. ->with($password)
  854. ->will($this->throwException(new InvalidTokenException()));
  855. $this->tokenProvider->expects($this->once())
  856. ->method('generateToken')
  857. ->with($sessionId, $uid, $loginName, $password, 'Firefox', IToken::TEMPORARY_TOKEN, IToken::REMEMBER);
  858. $this->assertTrue($userSession->createSessionToken($request, $uid, $loginName, $password, true));
  859. }
  860. public function testCreateSessionTokenWithTokenPassword() {
  861. $manager = $this->getMockBuilder(Manager::class)
  862. ->disableOriginalConstructor()
  863. ->getMock();
  864. $session = $this->createMock(ISession::class);
  865. $token = $this->createMock(IToken::class);
  866. $user = $this->createMock(IUser::class);
  867. $userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
  868. $requestId = $this->createMock(IRequestId::class);
  869. $config = $this->createMock(IConfig::class);
  870. $csrf = $this->getMockBuilder(CsrfTokenManager::class)
  871. ->disableOriginalConstructor()
  872. ->getMock();
  873. $request = new Request([
  874. 'server' => [
  875. 'HTTP_USER_AGENT' => 'Firefox',
  876. ]
  877. ], $requestId, $config, $csrf);
  878. $uid = 'user123';
  879. $loginName = 'User123';
  880. $password = 'iamatoken';
  881. $realPassword = 'passme';
  882. $sessionId = 'abcxyz';
  883. $manager->expects($this->once())
  884. ->method('get')
  885. ->with($uid)
  886. ->willReturn($user);
  887. $session->expects($this->once())
  888. ->method('getId')
  889. ->willReturn($sessionId);
  890. $this->tokenProvider->expects($this->once())
  891. ->method('getToken')
  892. ->with($password)
  893. ->willReturn($token);
  894. $this->tokenProvider->expects($this->once())
  895. ->method('getPassword')
  896. ->with($token, $password)
  897. ->willReturn($realPassword);
  898. $this->tokenProvider->expects($this->once())
  899. ->method('generateToken')
  900. ->with($sessionId, $uid, $loginName, $realPassword, 'Firefox', IToken::TEMPORARY_TOKEN, IToken::DO_NOT_REMEMBER);
  901. $this->assertTrue($userSession->createSessionToken($request, $uid, $loginName, $password));
  902. }
  903. public function testCreateSessionTokenWithNonExistentUser() {
  904. $manager = $this->getMockBuilder(Manager::class)
  905. ->disableOriginalConstructor()
  906. ->getMock();
  907. $session = $this->createMock(ISession::class);
  908. $userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
  909. $request = $this->createMock(IRequest::class);
  910. $uid = 'user123';
  911. $loginName = 'User123';
  912. $password = 'passme';
  913. $manager->expects($this->once())
  914. ->method('get')
  915. ->with($uid)
  916. ->willReturn(null);
  917. $this->assertFalse($userSession->createSessionToken($request, $uid, $loginName, $password));
  918. }
  919. public function testCreateRememberMeToken() {
  920. $user = $this->createMock(IUser::class);
  921. $user
  922. ->expects($this->exactly(2))
  923. ->method('getUID')
  924. ->willReturn('UserUid');
  925. $this->random
  926. ->expects($this->once())
  927. ->method('generate')
  928. ->with(32)
  929. ->willReturn('LongRandomToken');
  930. $this->config
  931. ->expects($this->once())
  932. ->method('setUserValue')
  933. ->with('UserUid', 'login_token', 'LongRandomToken', 10000);
  934. $this->userSession
  935. ->expects($this->once())
  936. ->method('setMagicInCookie')
  937. ->with('UserUid', 'LongRandomToken');
  938. $this->userSession->createRememberMeToken($user);
  939. }
  940. public function testTryBasicAuthLoginValid() {
  941. $request = $this->createMock(Request::class);
  942. $request->method('__get')
  943. ->willReturn([
  944. 'PHP_AUTH_USER' => 'username',
  945. 'PHP_AUTH_PW' => 'password',
  946. ]);
  947. $request->method('__isset')
  948. ->with('server')
  949. ->willReturn(true);
  950. $davAuthenticatedSet = false;
  951. $lastPasswordConfirmSet = false;
  952. $this->session
  953. ->method('set')
  954. ->willReturnCallback(function ($k, $v) use (&$davAuthenticatedSet, &$lastPasswordConfirmSet) {
  955. switch ($k) {
  956. case Auth::DAV_AUTHENTICATED:
  957. $davAuthenticatedSet = $v;
  958. return;
  959. case 'last-password-confirm':
  960. $lastPasswordConfirmSet = 1000;
  961. return;
  962. default:
  963. throw new \Exception();
  964. }
  965. });
  966. $userSession = $this->getMockBuilder(Session::class)
  967. ->setConstructorArgs([
  968. $this->manager,
  969. $this->session,
  970. $this->timeFactory,
  971. $this->tokenProvider,
  972. $this->config,
  973. $this->random,
  974. $this->lockdownManager,
  975. $this->logger,
  976. $this->dispatcher
  977. ])
  978. ->setMethods([
  979. 'logClientIn',
  980. 'getUser',
  981. ])
  982. ->getMock();
  983. /** @var Session|MockObject */
  984. $userSession->expects($this->once())
  985. ->method('logClientIn')
  986. ->with(
  987. $this->equalTo('username'),
  988. $this->equalTo('password'),
  989. $this->equalTo($request),
  990. $this->equalTo($this->throttler)
  991. )->willReturn(true);
  992. $user = $this->createMock(IUser::class);
  993. $user->method('getUID')->willReturn('username');
  994. $userSession->expects($this->once())
  995. ->method('getUser')
  996. ->willReturn($user);
  997. $this->assertTrue($userSession->tryBasicAuthLogin($request, $this->throttler));
  998. $this->assertSame('username', $davAuthenticatedSet);
  999. $this->assertSame(1000, $lastPasswordConfirmSet);
  1000. }
  1001. public function testTryBasicAuthLoginNoLogin() {
  1002. $request = $this->createMock(Request::class);
  1003. $request->method('__get')
  1004. ->willReturn([]);
  1005. $request->method('__isset')
  1006. ->with('server')
  1007. ->willReturn(true);
  1008. $this->session->expects($this->never())
  1009. ->method($this->anything());
  1010. $userSession = $this->getMockBuilder(Session::class)
  1011. ->setConstructorArgs([
  1012. $this->manager,
  1013. $this->session,
  1014. $this->timeFactory,
  1015. $this->tokenProvider,
  1016. $this->config,
  1017. $this->random,
  1018. $this->lockdownManager,
  1019. $this->logger,
  1020. $this->dispatcher
  1021. ])
  1022. ->setMethods([
  1023. 'logClientIn',
  1024. ])
  1025. ->getMock();
  1026. /** @var Session|MockObject */
  1027. $userSession->expects($this->never())
  1028. ->method('logClientIn');
  1029. $this->assertFalse($userSession->tryBasicAuthLogin($request, $this->throttler));
  1030. }
  1031. public function testUpdateTokens() {
  1032. $this->tokenProvider->expects($this->once())
  1033. ->method('updatePasswords')
  1034. ->with('uid', 'pass');
  1035. $this->userSession->updateTokens('uid', 'pass');
  1036. }
  1037. public function testLogClientInThrottlerUsername() {
  1038. $manager = $this->createMock(Manager::class);
  1039. $session = $this->createMock(ISession::class);
  1040. $request = $this->createMock(IRequest::class);
  1041. /** @var Session $userSession */
  1042. $userSession = $this->getMockBuilder(Session::class)
  1043. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  1044. ->setMethods(['isTokenPassword', 'login', 'supportsCookies', 'createSessionToken', 'getUser'])
  1045. ->getMock();
  1046. $userSession->expects($this->once())
  1047. ->method('isTokenPassword')
  1048. ->willReturn(true);
  1049. $userSession->expects($this->once())
  1050. ->method('login')
  1051. ->with('john', 'I-AM-AN-PASSWORD')
  1052. ->willReturn(false);
  1053. $session->expects($this->never())
  1054. ->method('set');
  1055. $request
  1056. ->method('getRemoteAddress')
  1057. ->willReturn('192.168.0.1');
  1058. $this->throttler
  1059. ->expects($this->exactly(2))
  1060. ->method('sleepDelayOrThrowOnMax')
  1061. ->with('192.168.0.1');
  1062. $this->throttler
  1063. ->expects($this->any())
  1064. ->method('getDelay')
  1065. ->with('192.168.0.1')
  1066. ->willReturn(0);
  1067. $this->throttler
  1068. ->expects($this->once())
  1069. ->method('registerAttempt')
  1070. ->with('login', '192.168.0.1', ['user' => 'john']);
  1071. $this->dispatcher
  1072. ->expects($this->once())
  1073. ->method('dispatchTyped')
  1074. ->with(new LoginFailed('john', 'I-AM-AN-PASSWORD'));
  1075. $this->assertFalse($userSession->logClientIn('john', 'I-AM-AN-PASSWORD', $request, $this->throttler));
  1076. }
  1077. public function testLogClientInThrottlerEmail() {
  1078. $manager = $this->createMock(Manager::class);
  1079. $session = $this->createMock(ISession::class);
  1080. $request = $this->createMock(IRequest::class);
  1081. /** @var Session $userSession */
  1082. $userSession = $this->getMockBuilder(Session::class)
  1083. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
  1084. ->setMethods(['isTokenPassword', 'login', 'supportsCookies', 'createSessionToken', 'getUser'])
  1085. ->getMock();
  1086. $userSession->expects($this->once())
  1087. ->method('isTokenPassword')
  1088. ->willReturn(false);
  1089. $userSession->expects($this->once())
  1090. ->method('login')
  1091. ->with('john@foo.bar', 'I-AM-AN-PASSWORD')
  1092. ->willReturn(false);
  1093. $manager
  1094. ->method('getByEmail')
  1095. ->with('john@foo.bar')
  1096. ->willReturn([]);
  1097. $session->expects($this->never())
  1098. ->method('set');
  1099. $request
  1100. ->method('getRemoteAddress')
  1101. ->willReturn('192.168.0.1');
  1102. $this->throttler
  1103. ->expects($this->exactly(2))
  1104. ->method('sleepDelayOrThrowOnMax')
  1105. ->with('192.168.0.1');
  1106. $this->throttler
  1107. ->expects($this->any())
  1108. ->method('getDelay')
  1109. ->with('192.168.0.1')
  1110. ->willReturn(0);
  1111. $this->throttler
  1112. ->expects($this->once())
  1113. ->method('registerAttempt')
  1114. ->with('login', '192.168.0.1', ['user' => 'john@foo.bar']);
  1115. $this->dispatcher
  1116. ->expects($this->once())
  1117. ->method('dispatchTyped')
  1118. ->with(new LoginFailed('john@foo.bar', 'I-AM-AN-PASSWORD'));
  1119. $this->assertFalse($userSession->logClientIn('john@foo.bar', 'I-AM-AN-PASSWORD', $request, $this->throttler));
  1120. }
  1121. }