SessionTest.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  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\Authentication\Token\IProvider;
  10. use OC\Authentication\Token\IToken;
  11. use OC\Security\Bruteforce\Throttler;
  12. use OC\Session\Memory;
  13. use OC\User\Manager;
  14. use OC\User\Session;
  15. use OC\User\User;
  16. use OCP\AppFramework\Utility\ITimeFactory;
  17. use OCP\IConfig;
  18. use OCP\IRequest;
  19. use OCP\ISession;
  20. use OCP\IUser;
  21. use OCP\IUserManager;
  22. use OCP\Security\ISecureRandom;
  23. /**
  24. * @group DB
  25. * @package Test\User
  26. */
  27. class SessionTest extends \Test\TestCase {
  28. /** @var \OCP\AppFramework\Utility\ITimeFactory */
  29. private $timeFactory;
  30. /** @var \OC\Authentication\Token\DefaultTokenProvider */
  31. protected $tokenProvider;
  32. /** @var \OCP\IConfig */
  33. private $config;
  34. /** @var Throttler */
  35. private $throttler;
  36. protected function setUp() {
  37. parent::setUp();
  38. $this->timeFactory = $this->createMock(ITimeFactory::class);
  39. $this->timeFactory->expects($this->any())
  40. ->method('getTime')
  41. ->will($this->returnValue(10000));
  42. $this->tokenProvider = $this->createMock(IProvider::class);
  43. $this->config = $this->createMock(IConfig::class);
  44. $this->throttler = $this->createMock(Throttler::class);
  45. }
  46. public function testGetUser() {
  47. $token = new \OC\Authentication\Token\DefaultToken();
  48. $token->setLoginName('User123');
  49. $token->setLastCheck(200);
  50. $expectedUser = $this->createMock(IUser::class);
  51. $expectedUser->expects($this->any())
  52. ->method('getUID')
  53. ->will($this->returnValue('user123'));
  54. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  55. $session->expects($this->at(0))
  56. ->method('get')
  57. ->with('user_id')
  58. ->will($this->returnValue($expectedUser->getUID()));
  59. $sessionId = 'abcdef12345';
  60. $manager = $this->getMockBuilder('\OC\User\Manager')
  61. ->disableOriginalConstructor()
  62. ->getMock();
  63. $session->expects($this->at(1))
  64. ->method('get')
  65. ->with('app_password')
  66. ->will($this->returnValue(null)); // No password set -> browser session
  67. $session->expects($this->once())
  68. ->method('getId')
  69. ->will($this->returnValue($sessionId));
  70. $this->tokenProvider->expects($this->once())
  71. ->method('getToken')
  72. ->with($sessionId)
  73. ->will($this->returnValue($token));
  74. $this->tokenProvider->expects($this->once())
  75. ->method('getPassword')
  76. ->with($token, $sessionId)
  77. ->will($this->returnValue('passme'));
  78. $manager->expects($this->once())
  79. ->method('checkPassword')
  80. ->with('User123', 'passme')
  81. ->will($this->returnValue(true));
  82. $expectedUser->expects($this->once())
  83. ->method('isEnabled')
  84. ->will($this->returnValue(true));
  85. $this->tokenProvider->expects($this->once())
  86. ->method('updateTokenActivity')
  87. ->with($token);
  88. $manager->expects($this->any())
  89. ->method('get')
  90. ->with($expectedUser->getUID())
  91. ->will($this->returnValue($expectedUser));
  92. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  93. $user = $userSession->getUser();
  94. $this->assertSame($expectedUser, $user);
  95. $this->assertSame(10000, $token->getLastCheck());
  96. }
  97. public function isLoggedInData() {
  98. return [
  99. [true],
  100. [false],
  101. ];
  102. }
  103. /**
  104. * @dataProvider isLoggedInData
  105. */
  106. public function testIsLoggedIn($isLoggedIn) {
  107. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  108. $manager = $this->getMockBuilder('\OC\User\Manager')
  109. ->disableOriginalConstructor()
  110. ->getMock();
  111. $userSession = $this->getMockBuilder('\OC\User\Session')
  112. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
  113. ->setMethods([
  114. 'getUser'
  115. ])
  116. ->getMock();
  117. $user = new User('sepp', null);
  118. $userSession->expects($this->once())
  119. ->method('getUser')
  120. ->will($this->returnValue($isLoggedIn ? $user : null));
  121. $this->assertEquals($isLoggedIn, $userSession->isLoggedIn());
  122. }
  123. public function testSetUser() {
  124. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  125. $session->expects($this->once())
  126. ->method('set')
  127. ->with('user_id', 'foo');
  128. $manager = $this->createMock(Manager::class);
  129. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  130. $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock();
  131. $user->expects($this->once())
  132. ->method('getUID')
  133. ->will($this->returnValue('foo'));
  134. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  135. $userSession->setUser($user);
  136. }
  137. public function testLoginValidPasswordEnabled() {
  138. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  139. $session->expects($this->once())
  140. ->method('regenerateId');
  141. $this->tokenProvider->expects($this->once())
  142. ->method('getToken')
  143. ->with('bar')
  144. ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
  145. $session->expects($this->exactly(2))
  146. ->method('set')
  147. ->with($this->callback(function ($key) {
  148. switch ($key) {
  149. case 'user_id':
  150. case 'loginname':
  151. return true;
  152. break;
  153. default:
  154. return false;
  155. break;
  156. }
  157. }, 'foo'));
  158. $managerMethods = get_class_methods('\OC\User\Manager');
  159. //keep following methods intact in order to ensure hooks are
  160. //working
  161. $doNotMock = array('__construct', 'emit', 'listen');
  162. foreach ($doNotMock as $methodName) {
  163. $i = array_search($methodName, $managerMethods, true);
  164. if ($i !== false) {
  165. unset($managerMethods[$i]);
  166. }
  167. }
  168. $manager = $this->getMockBuilder(Manager::class)->setMethods($managerMethods)->getMock();
  169. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  170. $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock();
  171. $user->expects($this->any())
  172. ->method('isEnabled')
  173. ->will($this->returnValue(true));
  174. $user->expects($this->any())
  175. ->method('getUID')
  176. ->will($this->returnValue('foo'));
  177. $user->expects($this->once())
  178. ->method('updateLastLoginTimestamp');
  179. $manager->expects($this->once())
  180. ->method('checkPassword')
  181. ->with('foo', 'bar')
  182. ->will($this->returnValue($user));
  183. $userSession = $this->getMockBuilder('\OC\User\Session')
  184. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
  185. ->setMethods([
  186. 'prepareUserLogin'
  187. ])
  188. ->getMock();
  189. $userSession->expects($this->once())
  190. ->method('prepareUserLogin');
  191. $userSession->login('foo', 'bar');
  192. $this->assertEquals($user, $userSession->getUser());
  193. }
  194. /**
  195. * @expectedException \OC\User\LoginException
  196. */
  197. public function testLoginValidPasswordDisabled() {
  198. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  199. $session->expects($this->never())
  200. ->method('set');
  201. $session->expects($this->once())
  202. ->method('regenerateId');
  203. $this->tokenProvider->expects($this->once())
  204. ->method('getToken')
  205. ->with('bar')
  206. ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
  207. $managerMethods = get_class_methods('\OC\User\Manager');
  208. //keep following methods intact in order to ensure hooks are
  209. //working
  210. $doNotMock = array('__construct', 'emit', 'listen');
  211. foreach ($doNotMock as $methodName) {
  212. $i = array_search($methodName, $managerMethods, true);
  213. if ($i !== false) {
  214. unset($managerMethods[$i]);
  215. }
  216. }
  217. $manager = $this->getMockBuilder(Manager::class)->setMethods($managerMethods)->getMock();
  218. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  219. $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock();
  220. $user->expects($this->any())
  221. ->method('isEnabled')
  222. ->will($this->returnValue(false));
  223. $user->expects($this->never())
  224. ->method('updateLastLoginTimestamp');
  225. $manager->expects($this->once())
  226. ->method('checkPassword')
  227. ->with('foo', 'bar')
  228. ->will($this->returnValue($user));
  229. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  230. $userSession->login('foo', 'bar');
  231. }
  232. public function testLoginInvalidPassword() {
  233. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  234. $managerMethods = get_class_methods('\OC\User\Manager');
  235. //keep following methods intact in order to ensure hooks are
  236. //working
  237. $doNotMock = array('__construct', 'emit', 'listen');
  238. foreach ($doNotMock as $methodName) {
  239. $i = array_search($methodName, $managerMethods, true);
  240. if ($i !== false) {
  241. unset($managerMethods[$i]);
  242. }
  243. }
  244. $manager = $this->getMockBuilder(Manager::class)->setMethods($managerMethods)->getMock();
  245. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  246. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  247. $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock();
  248. $session->expects($this->never())
  249. ->method('set');
  250. $session->expects($this->once())
  251. ->method('regenerateId');
  252. $this->tokenProvider->expects($this->once())
  253. ->method('getToken')
  254. ->with('bar')
  255. ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
  256. $user->expects($this->never())
  257. ->method('isEnabled');
  258. $user->expects($this->never())
  259. ->method('updateLastLoginTimestamp');
  260. $manager->expects($this->once())
  261. ->method('checkPassword')
  262. ->with('foo', 'bar')
  263. ->will($this->returnValue(false));
  264. $userSession->login('foo', 'bar');
  265. }
  266. public function testLoginNonExisting() {
  267. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  268. $manager = $this->createMock(Manager::class);
  269. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  270. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  271. $session->expects($this->never())
  272. ->method('set');
  273. $session->expects($this->once())
  274. ->method('regenerateId');
  275. $this->tokenProvider->expects($this->once())
  276. ->method('getToken')
  277. ->with('bar')
  278. ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
  279. $manager->expects($this->once())
  280. ->method('checkPassword')
  281. ->with('foo', 'bar')
  282. ->will($this->returnValue(false));
  283. $userSession->login('foo', 'bar');
  284. }
  285. /**
  286. * When using a device token, the loginname must match the one that was used
  287. * when generating the token on the browser.
  288. */
  289. public function testLoginWithDifferentTokenLoginName() {
  290. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  291. $manager = $this->createMock(Manager::class);
  292. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  293. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  294. $username = 'user123';
  295. $token = new \OC\Authentication\Token\DefaultToken();
  296. $token->setLoginName($username);
  297. $session->expects($this->never())
  298. ->method('set');
  299. $session->expects($this->once())
  300. ->method('regenerateId');
  301. $this->tokenProvider->expects($this->once())
  302. ->method('getToken')
  303. ->with('bar')
  304. ->will($this->returnValue($token));
  305. $manager->expects($this->once())
  306. ->method('checkPassword')
  307. ->with('foo', 'bar')
  308. ->will($this->returnValue(false));
  309. $userSession->login('foo', 'bar');
  310. }
  311. /**
  312. * @expectedException \OC\Authentication\Exceptions\PasswordLoginForbiddenException
  313. */
  314. public function testLogClientInNoTokenPasswordWith2fa() {
  315. $manager = $this->getMockBuilder('\OC\User\Manager')
  316. ->disableOriginalConstructor()
  317. ->getMock();
  318. $session = $this->createMock(ISession::class);
  319. $request = $this->createMock(IRequest::class);
  320. /** @var \OC\User\Session $userSession */
  321. $userSession = $this->getMockBuilder('\OC\User\Session')
  322. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
  323. ->setMethods(['login', 'supportsCookies', 'createSessionToken', 'getUser'])
  324. ->getMock();
  325. $this->tokenProvider->expects($this->once())
  326. ->method('getToken')
  327. ->with('doe')
  328. ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
  329. $this->config->expects($this->once())
  330. ->method('getSystemValue')
  331. ->with('token_auth_enforced', false)
  332. ->will($this->returnValue(true));
  333. $request
  334. ->expects($this->any())
  335. ->method('getRemoteAddress')
  336. ->willReturn('192.168.0.1');
  337. $this->throttler
  338. ->expects($this->once())
  339. ->method('sleepDelay')
  340. ->with('192.168.0.1');
  341. $this->throttler
  342. ->expects($this->any())
  343. ->method('getDelay')
  344. ->with('192.168.0.1')
  345. ->willReturn(0);
  346. $userSession->logClientIn('john', 'doe', $request, $this->throttler);
  347. }
  348. public function testLogClientInWithTokenPassword() {
  349. $manager = $this->getMockBuilder('\OC\User\Manager')
  350. ->disableOriginalConstructor()
  351. ->getMock();
  352. $session = $this->createMock(ISession::class);
  353. $request = $this->createMock(IRequest::class);
  354. /** @var \OC\User\Session $userSession */
  355. $userSession = $this->getMockBuilder('\OC\User\Session')
  356. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
  357. ->setMethods(['isTokenPassword', 'login', 'supportsCookies', 'createSessionToken', 'getUser'])
  358. ->getMock();
  359. $userSession->expects($this->once())
  360. ->method('isTokenPassword')
  361. ->will($this->returnValue(true));
  362. $userSession->expects($this->once())
  363. ->method('login')
  364. ->with('john', 'I-AM-AN-APP-PASSWORD')
  365. ->will($this->returnValue(true));
  366. $session->expects($this->once())
  367. ->method('set')
  368. ->with('app_password', 'I-AM-AN-APP-PASSWORD');
  369. $request
  370. ->expects($this->any())
  371. ->method('getRemoteAddress')
  372. ->willReturn('192.168.0.1');
  373. $this->throttler
  374. ->expects($this->once())
  375. ->method('sleepDelay')
  376. ->with('192.168.0.1');
  377. $this->throttler
  378. ->expects($this->any())
  379. ->method('getDelay')
  380. ->with('192.168.0.1')
  381. ->willReturn(0);
  382. $this->assertTrue($userSession->logClientIn('john', 'I-AM-AN-APP-PASSWORD', $request, $this->throttler));
  383. }
  384. /**
  385. * @expectedException \OC\Authentication\Exceptions\PasswordLoginForbiddenException
  386. */
  387. public function testLogClientInNoTokenPasswordNo2fa() {
  388. $manager = $this->getMockBuilder('\OC\User\Manager')
  389. ->disableOriginalConstructor()
  390. ->getMock();
  391. $session = $this->createMock(ISession::class);
  392. $request = $this->createMock(IRequest::class);
  393. /** @var \OC\User\Session $userSession */
  394. $userSession = $this->getMockBuilder('\OC\User\Session')
  395. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
  396. ->setMethods(['login', 'isTwoFactorEnforced'])
  397. ->getMock();
  398. $this->tokenProvider->expects($this->once())
  399. ->method('getToken')
  400. ->with('doe')
  401. ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
  402. $this->config->expects($this->once())
  403. ->method('getSystemValue')
  404. ->with('token_auth_enforced', false)
  405. ->will($this->returnValue(false));
  406. $userSession->expects($this->once())
  407. ->method('isTwoFactorEnforced')
  408. ->with('john')
  409. ->will($this->returnValue(true));
  410. $request
  411. ->expects($this->any())
  412. ->method('getRemoteAddress')
  413. ->willReturn('192.168.0.1');
  414. $this->throttler
  415. ->expects($this->once())
  416. ->method('sleepDelay')
  417. ->with('192.168.0.1');
  418. $this->throttler
  419. ->expects($this->any())
  420. ->method('getDelay')
  421. ->with('192.168.0.1')
  422. ->willReturn(0);
  423. $userSession->logClientIn('john', 'doe', $request, $this->throttler);
  424. }
  425. public function testRememberLoginValidToken() {
  426. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  427. $session->expects($this->exactly(1))
  428. ->method('set')
  429. ->with($this->callback(function ($key) {
  430. switch ($key) {
  431. case 'user_id':
  432. return true;
  433. default:
  434. return false;
  435. }
  436. }, 'foo'));
  437. $session->expects($this->once())
  438. ->method('regenerateId');
  439. $managerMethods = get_class_methods('\OC\User\Manager');
  440. //keep following methods intact in order to ensure hooks are
  441. //working
  442. $doNotMock = array('__construct', 'emit', 'listen');
  443. foreach ($doNotMock as $methodName) {
  444. $i = array_search($methodName, $managerMethods, true);
  445. if ($i !== false) {
  446. unset($managerMethods[$i]);
  447. }
  448. }
  449. $manager = $this->getMockBuilder(Manager::class)->setMethods($managerMethods)->getMock();
  450. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  451. $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock();
  452. $user->expects($this->any())
  453. ->method('getUID')
  454. ->will($this->returnValue('foo'));
  455. $user->expects($this->once())
  456. ->method('updateLastLoginTimestamp');
  457. $manager->expects($this->once())
  458. ->method('get')
  459. ->with('foo')
  460. ->will($this->returnValue($user));
  461. //prepare login token
  462. $token = 'goodToken';
  463. \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time());
  464. $userSession = $this->getMockBuilder(Session::class)
  465. //override, otherwise tests will fail because of setcookie()
  466. ->setMethods(['setMagicInCookie'])
  467. //there are passed as parameters to the constructor
  468. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
  469. ->getMock();
  470. $granted = $userSession->loginWithCookie('foo', $token);
  471. $this->assertSame($granted, true);
  472. }
  473. public function testRememberLoginInvalidToken() {
  474. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  475. $session->expects($this->never())
  476. ->method('set');
  477. $session->expects($this->once())
  478. ->method('regenerateId');
  479. $managerMethods = get_class_methods('\OC\User\Manager');
  480. //keep following methods intact in order to ensure hooks are
  481. //working
  482. $doNotMock = array('__construct', 'emit', 'listen');
  483. foreach ($doNotMock as $methodName) {
  484. $i = array_search($methodName, $managerMethods, true);
  485. if ($i !== false) {
  486. unset($managerMethods[$i]);
  487. }
  488. }
  489. $manager = $this->getMockBuilder(Manager::class)->setMethods($managerMethods)->getMock();
  490. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  491. $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock();
  492. $user->expects($this->any())
  493. ->method('getUID')
  494. ->will($this->returnValue('foo'));
  495. $user->expects($this->never())
  496. ->method('updateLastLoginTimestamp');
  497. $manager->expects($this->once())
  498. ->method('get')
  499. ->with('foo')
  500. ->will($this->returnValue($user));
  501. //prepare login token
  502. $token = 'goodToken';
  503. \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time());
  504. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  505. $granted = $userSession->loginWithCookie('foo', 'badToken');
  506. $this->assertSame($granted, false);
  507. }
  508. public function testRememberLoginInvalidUser() {
  509. $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
  510. $session->expects($this->never())
  511. ->method('set');
  512. $session->expects($this->once())
  513. ->method('regenerateId');
  514. $managerMethods = get_class_methods('\OC\User\Manager');
  515. //keep following methods intact in order to ensure hooks are
  516. //working
  517. $doNotMock = array('__construct', 'emit', 'listen');
  518. foreach ($doNotMock as $methodName) {
  519. $i = array_search($methodName, $managerMethods, true);
  520. if ($i !== false) {
  521. unset($managerMethods[$i]);
  522. }
  523. }
  524. $manager = $this->getMockBuilder(Manager::class)->setMethods($managerMethods)->getMock();
  525. $backend = $this->createMock(\Test\Util\User\Dummy::class);
  526. $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock();
  527. $user->expects($this->never())
  528. ->method('getUID');
  529. $user->expects($this->never())
  530. ->method('updateLastLoginTimestamp');
  531. $manager->expects($this->once())
  532. ->method('get')
  533. ->with('foo')
  534. ->will($this->returnValue(null));
  535. //prepare login token
  536. $token = 'goodToken';
  537. \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time());
  538. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  539. $granted = $userSession->loginWithCookie('foo', $token);
  540. $this->assertSame($granted, false);
  541. }
  542. public function testActiveUserAfterSetSession() {
  543. $users = array(
  544. 'foo' => new User('foo', null),
  545. 'bar' => new User('bar', null)
  546. );
  547. $manager = $this->getMockBuilder('\OC\User\Manager')
  548. ->disableOriginalConstructor()
  549. ->getMock();
  550. $manager->expects($this->any())
  551. ->method('get')
  552. ->will($this->returnCallback(function ($uid) use ($users) {
  553. return $users[$uid];
  554. }));
  555. $session = new Memory('');
  556. $session->set('user_id', 'foo');
  557. $userSession = $this->getMockBuilder('\OC\User\Session')
  558. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
  559. ->setMethods([
  560. 'validateSession'
  561. ])
  562. ->getMock();
  563. $userSession->expects($this->any())
  564. ->method('validateSession');
  565. $this->assertEquals($users['foo'], $userSession->getUser());
  566. $session2 = new Memory('');
  567. $session2->set('user_id', 'bar');
  568. $userSession->setSession($session2);
  569. $this->assertEquals($users['bar'], $userSession->getUser());
  570. }
  571. public function testCreateSessionToken() {
  572. $manager = $this->createMock(Manager::class);
  573. $session = $this->createMock(ISession::class);
  574. $token = $this->createMock(IToken::class);
  575. $user = $this->createMock(IUser::class);
  576. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  577. $random = $this->createMock(ISecureRandom::class);
  578. $config = $this->createMock(IConfig::class);
  579. $csrf = $this->getMockBuilder('\OC\Security\CSRF\CsrfTokenManager')
  580. ->disableOriginalConstructor()
  581. ->getMock();
  582. $request = new \OC\AppFramework\Http\Request([
  583. 'server' => [
  584. 'HTTP_USER_AGENT' => 'Firefox',
  585. ]
  586. ], $random, $config, $csrf);
  587. $uid = 'user123';
  588. $loginName = 'User123';
  589. $password = 'passme';
  590. $sessionId = 'abcxyz';
  591. $manager->expects($this->once())
  592. ->method('get')
  593. ->with($uid)
  594. ->will($this->returnValue($user));
  595. $session->expects($this->once())
  596. ->method('getId')
  597. ->will($this->returnValue($sessionId));
  598. $this->tokenProvider->expects($this->once())
  599. ->method('getToken')
  600. ->with($password)
  601. ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
  602. $this->tokenProvider->expects($this->once())
  603. ->method('generateToken')
  604. ->with($sessionId, $uid, $loginName, $password, 'Firefox');
  605. $this->assertTrue($userSession->createSessionToken($request, $uid, $loginName, $password));
  606. }
  607. public function testCreateSessionTokenWithTokenPassword() {
  608. $manager = $this->getMockBuilder('\OC\User\Manager')
  609. ->disableOriginalConstructor()
  610. ->getMock();
  611. $session = $this->createMock(ISession::class);
  612. $token = $this->createMock(IToken::class);
  613. $user = $this->createMock(IUser::class);
  614. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  615. $random = $this->createMock(ISecureRandom::class);
  616. $config = $this->createMock(IConfig::class);
  617. $csrf = $this->getMockBuilder('\OC\Security\CSRF\CsrfTokenManager')
  618. ->disableOriginalConstructor()
  619. ->getMock();
  620. $request = new \OC\AppFramework\Http\Request([
  621. 'server' => [
  622. 'HTTP_USER_AGENT' => 'Firefox',
  623. ]
  624. ], $random, $config, $csrf);
  625. $uid = 'user123';
  626. $loginName = 'User123';
  627. $password = 'iamatoken';
  628. $realPassword = 'passme';
  629. $sessionId = 'abcxyz';
  630. $manager->expects($this->once())
  631. ->method('get')
  632. ->with($uid)
  633. ->will($this->returnValue($user));
  634. $session->expects($this->once())
  635. ->method('getId')
  636. ->will($this->returnValue($sessionId));
  637. $this->tokenProvider->expects($this->once())
  638. ->method('getToken')
  639. ->with($password)
  640. ->will($this->returnValue($token));
  641. $this->tokenProvider->expects($this->once())
  642. ->method('getPassword')
  643. ->with($token, $password)
  644. ->will($this->returnValue($realPassword));
  645. $this->tokenProvider->expects($this->once())
  646. ->method('generateToken')
  647. ->with($sessionId, $uid, $loginName, $realPassword, 'Firefox');
  648. $this->assertTrue($userSession->createSessionToken($request, $uid, $loginName, $password));
  649. }
  650. public function testCreateSessionTokenWithNonExistentUser() {
  651. $manager = $this->getMockBuilder('\OC\User\Manager')
  652. ->disableOriginalConstructor()
  653. ->getMock();
  654. $session = $this->createMock(ISession::class);
  655. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
  656. $request = $this->createMock(IRequest::class);
  657. $uid = 'user123';
  658. $loginName = 'User123';
  659. $password = 'passme';
  660. $manager->expects($this->once())
  661. ->method('get')
  662. ->with($uid)
  663. ->will($this->returnValue(null));
  664. $this->assertFalse($userSession->createSessionToken($request, $uid, $loginName, $password));
  665. }
  666. /**
  667. * @expectedException \OC\User\LoginException
  668. */
  669. public function testTryTokenLoginWithDisabledUser() {
  670. $manager = $this->getMockBuilder('\OC\User\Manager')
  671. ->disableOriginalConstructor()
  672. ->getMock();
  673. $session = new Memory('');
  674. $token = new \OC\Authentication\Token\DefaultToken();
  675. $token->setLoginName('fritz');
  676. $token->setUid('fritz0');
  677. $token->setLastCheck(100); // Needs check
  678. $user = $this->createMock(IUser::class);
  679. $userSession = $this->getMockBuilder('\OC\User\Session')
  680. ->setMethods(['logout'])
  681. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
  682. ->getMock();
  683. $request = $this->createMock(IRequest::class);
  684. $request->expects($this->once())
  685. ->method('getHeader')
  686. ->with('Authorization')
  687. ->will($this->returnValue('token xxxxx'));
  688. $this->tokenProvider->expects($this->once())
  689. ->method('getToken')
  690. ->with('xxxxx')
  691. ->will($this->returnValue($token));
  692. $manager->expects($this->once())
  693. ->method('get')
  694. ->with('fritz0')
  695. ->will($this->returnValue($user));
  696. $user->expects($this->once())
  697. ->method('isEnabled')
  698. ->will($this->returnValue(false));
  699. $userSession->tryTokenLogin($request);
  700. }
  701. public function testValidateSessionDisabledUser() {
  702. $userManager = $this->createMock(IUserManager::class);
  703. $session = $this->createMock(ISession::class);
  704. $timeFactory = $this->createMock(ITimeFactory::class);
  705. $tokenProvider = $this->createMock(IProvider::class);
  706. $userSession = $this->getMockBuilder('\OC\User\Session')
  707. ->setConstructorArgs([$userManager, $session, $timeFactory, $tokenProvider, $this->config])
  708. ->setMethods(['logout'])
  709. ->getMock();
  710. $user = $this->createMock(IUser::class);
  711. $token = new \OC\Authentication\Token\DefaultToken();
  712. $token->setLoginName('susan');
  713. $token->setLastCheck(20);
  714. $session->expects($this->once())
  715. ->method('get')
  716. ->with('app_password')
  717. ->will($this->returnValue('APP-PASSWORD'));
  718. $tokenProvider->expects($this->once())
  719. ->method('getToken')
  720. ->with('APP-PASSWORD')
  721. ->will($this->returnValue($token));
  722. $timeFactory->expects($this->once())
  723. ->method('getTime')
  724. ->will($this->returnValue(1000)); // more than 5min since last check
  725. $tokenProvider->expects($this->once())
  726. ->method('getPassword')
  727. ->with($token, 'APP-PASSWORD')
  728. ->will($this->returnValue('123456'));
  729. $userManager->expects($this->once())
  730. ->method('checkPassword')
  731. ->with('susan', '123456')
  732. ->will($this->returnValue(true));
  733. $user->expects($this->once())
  734. ->method('isEnabled')
  735. ->will($this->returnValue(false));
  736. $tokenProvider->expects($this->once())
  737. ->method('invalidateToken')
  738. ->with('APP-PASSWORD');
  739. $userSession->expects($this->once())
  740. ->method('logout');
  741. $userSession->setUser($user);
  742. $this->invokePrivate($userSession, 'validateSession');
  743. }
  744. public function testValidateSessionNoPassword() {
  745. $userManager = $this->createMock(IUserManager::class);
  746. $session = $this->createMock(ISession::class);
  747. $timeFactory = $this->createMock(ITimeFactory::class);
  748. $tokenProvider = $this->createMock(IProvider::class);
  749. $userSession = $this->getMockBuilder('\OC\User\Session')
  750. ->setConstructorArgs([$userManager, $session, $timeFactory, $tokenProvider, $this->config])
  751. ->setMethods(['logout'])
  752. ->getMock();
  753. $user = $this->createMock(IUser::class);
  754. $token = new \OC\Authentication\Token\DefaultToken();
  755. $token->setLastCheck(20);
  756. $session->expects($this->once())
  757. ->method('get')
  758. ->with('app_password')
  759. ->will($this->returnValue('APP-PASSWORD'));
  760. $tokenProvider->expects($this->once())
  761. ->method('getToken')
  762. ->with('APP-PASSWORD')
  763. ->will($this->returnValue($token));
  764. $timeFactory->expects($this->once())
  765. ->method('getTime')
  766. ->will($this->returnValue(1000)); // more than 5min since last check
  767. $tokenProvider->expects($this->once())
  768. ->method('getPassword')
  769. ->with($token, 'APP-PASSWORD')
  770. ->will($this->throwException(new \OC\Authentication\Exceptions\PasswordlessTokenException()));
  771. $tokenProvider->expects($this->once())
  772. ->method('updateToken')
  773. ->with($token);
  774. $this->invokePrivate($userSession, 'validateSession', [$user]);
  775. $this->assertEquals(1000, $token->getLastCheck());
  776. }
  777. public function testUpdateSessionTokenPassword() {
  778. $userManager = $this->createMock(IUserManager::class);
  779. $session = $this->createMock(ISession::class);
  780. $timeFactory = $this->createMock(ITimeFactory::class);
  781. $tokenProvider = $this->createMock(IProvider::class);
  782. $userSession = new \OC\User\Session($userManager, $session, $timeFactory, $tokenProvider, $this->config);
  783. $password = '123456';
  784. $sessionId ='session1234';
  785. $token = new \OC\Authentication\Token\DefaultToken();
  786. $session->expects($this->once())
  787. ->method('getId')
  788. ->will($this->returnValue($sessionId));
  789. $tokenProvider->expects($this->once())
  790. ->method('getToken')
  791. ->with($sessionId)
  792. ->will($this->returnValue($token));
  793. $tokenProvider->expects($this->once())
  794. ->method('setPassword')
  795. ->with($token, $sessionId, $password);
  796. $userSession->updateSessionTokenPassword($password);
  797. }
  798. public function testUpdateSessionTokenPasswordNoSessionAvailable() {
  799. $userManager = $this->createMock(IUserManager::class);
  800. $session = $this->createMock(ISession::class);
  801. $timeFactory = $this->createMock(ITimeFactory::class);
  802. $tokenProvider = $this->createMock(IProvider::class);
  803. $userSession = new \OC\User\Session($userManager, $session, $timeFactory, $tokenProvider, $this->config);
  804. $session->expects($this->once())
  805. ->method('getId')
  806. ->will($this->throwException(new \OCP\Session\Exceptions\SessionNotAvailableException()));
  807. $userSession->updateSessionTokenPassword('1234');
  808. }
  809. public function testUpdateSessionTokenPasswordInvalidTokenException() {
  810. $userManager = $this->createMock(IUserManager::class);
  811. $session = $this->createMock(ISession::class);
  812. $timeFactory = $this->createMock(ITimeFactory::class);
  813. $tokenProvider = $this->createMock(IProvider::class);
  814. $userSession = new \OC\User\Session($userManager, $session, $timeFactory, $tokenProvider, $this->config);
  815. $password = '123456';
  816. $sessionId ='session1234';
  817. $token = new \OC\Authentication\Token\DefaultToken();
  818. $session->expects($this->once())
  819. ->method('getId')
  820. ->will($this->returnValue($sessionId));
  821. $tokenProvider->expects($this->once())
  822. ->method('getToken')
  823. ->with($sessionId)
  824. ->will($this->returnValue($token));
  825. $tokenProvider->expects($this->once())
  826. ->method('setPassword')
  827. ->with($token, $sessionId, $password)
  828. ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
  829. $userSession->updateSessionTokenPassword($password);
  830. }
  831. }