You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PublicKeyTokenProviderTest.php 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2018 Roeland Jago Douma <roeland@famdouma.nl>
  4. *
  5. * @author Roeland Jago Douma <roeland@famdouma.nl>
  6. *
  7. * @license GNU AGPL version 3 or any later version
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as
  11. * published by the Free Software Foundation, either version 3 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. */
  23. namespace Test\Authentication\Token;
  24. use OC\Authentication\Exceptions\ExpiredTokenException;
  25. use OC\Authentication\Exceptions\InvalidTokenException;
  26. use OC\Authentication\Token\DefaultToken;
  27. use OC\Authentication\Token\IToken;
  28. use OC\Authentication\Token\PublicKeyToken;
  29. use OC\Authentication\Token\PublicKeyTokenMapper;
  30. use OC\Authentication\Token\PublicKeyTokenProvider;
  31. use OCP\AppFramework\Db\DoesNotExistException;
  32. use OCP\AppFramework\Utility\ITimeFactory;
  33. use OCP\IConfig;
  34. use OCP\ILogger;
  35. use OCP\Security\ICrypto;
  36. use Test\TestCase;
  37. class PublicKeyTokenProviderTest extends TestCase {
  38. /** @var PublicKeyTokenProvider|\PHPUnit\Framework\MockObject\MockObject */
  39. private $tokenProvider;
  40. /** @var PublicKeyTokenMapper|\PHPUnit\Framework\MockObject\MockObject */
  41. private $mapper;
  42. /** @var ICrypto */
  43. private $crypto;
  44. /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
  45. private $config;
  46. /** @var ILogger|\PHPUnit\Framework\MockObject\MockObject */
  47. private $logger;
  48. /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
  49. private $timeFactory;
  50. /** @var int */
  51. private $time;
  52. protected function setUp(): void {
  53. parent::setUp();
  54. $this->mapper = $this->createMock(PublicKeyTokenMapper::class);
  55. $this->crypto = \OC::$server->getCrypto();
  56. $this->config = $this->createMock(IConfig::class);
  57. $this->config->method('getSystemValue')
  58. ->willReturnMap([
  59. ['session_lifetime', 60 * 60 * 24, 150],
  60. ['remember_login_cookie_lifetime', 60 * 60 * 24 * 15, 300],
  61. ['secret', '', '1f4h9s'],
  62. ['openssl', [], []],
  63. ]);
  64. $this->logger = $this->createMock(ILogger::class);
  65. $this->timeFactory = $this->createMock(ITimeFactory::class);
  66. $this->time = 1313131;
  67. $this->timeFactory->method('getTime')
  68. ->willReturn($this->time);
  69. $this->tokenProvider = new PublicKeyTokenProvider($this->mapper, $this->crypto, $this->config, $this->logger,
  70. $this->timeFactory);
  71. }
  72. public function testGenerateToken() {
  73. $token = 'token';
  74. $uid = 'user';
  75. $user = 'User';
  76. $password = 'passme';
  77. $name = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  78. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  79. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  80. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12';
  81. $type = IToken::PERMANENT_TOKEN;
  82. $actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER);
  83. $this->assertInstanceOf(PublicKeyToken::class, $actual);
  84. $this->assertSame($uid, $actual->getUID());
  85. $this->assertSame($user, $actual->getLoginName());
  86. $this->assertSame($name, $actual->getName());
  87. $this->assertSame(IToken::DO_NOT_REMEMBER, $actual->getRemember());
  88. $this->assertSame($password, $this->tokenProvider->getPassword($actual, $token));
  89. }
  90. public function testUpdateToken() {
  91. $tk = new PublicKeyToken();
  92. $tk->setLastActivity($this->time - 200);
  93. $this->mapper->expects($this->once())
  94. ->method('update')
  95. ->with($tk);
  96. $this->tokenProvider->updateTokenActivity($tk);
  97. $this->assertEquals($this->time, $tk->getLastActivity());
  98. }
  99. public function testUpdateTokenDebounce() {
  100. $tk = new PublicKeyToken();
  101. $this->config->method('getSystemValueInt')
  102. ->willReturnCallback(function ($value, $default) {
  103. return $default;
  104. });
  105. $tk->setLastActivity($this->time - 30);
  106. $this->mapper->expects($this->never())
  107. ->method('update')
  108. ->with($tk);
  109. $this->tokenProvider->updateTokenActivity($tk);
  110. }
  111. public function testGetTokenByUser() {
  112. $this->mapper->expects($this->once())
  113. ->method('getTokenByUser')
  114. ->with('uid')
  115. ->willReturn(['token']);
  116. $this->assertEquals(['token'], $this->tokenProvider->getTokenByUser('uid'));
  117. }
  118. public function testGetPassword() {
  119. $token = 'token';
  120. $uid = 'user';
  121. $user = 'User';
  122. $password = 'passme';
  123. $name = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  124. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  125. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  126. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12';
  127. $type = IToken::PERMANENT_TOKEN;
  128. $actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER);
  129. $this->assertSame($password, $this->tokenProvider->getPassword($actual, $token));
  130. }
  131. public function testGetPasswordPasswordLessToken() {
  132. $this->expectException(\OC\Authentication\Exceptions\PasswordlessTokenException::class);
  133. $token = 'token1234';
  134. $tk = new PublicKeyToken();
  135. $tk->setPassword(null);
  136. $this->tokenProvider->getPassword($tk, $token);
  137. }
  138. public function testGetPasswordInvalidToken() {
  139. $this->expectException(\OC\Authentication\Exceptions\InvalidTokenException::class);
  140. $token = 'token';
  141. $uid = 'user';
  142. $user = 'User';
  143. $password = 'passme';
  144. $name = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  145. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  146. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  147. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12';
  148. $type = IToken::PERMANENT_TOKEN;
  149. $actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER);
  150. $this->tokenProvider->getPassword($actual, 'wrongtoken');
  151. }
  152. public function testSetPassword() {
  153. $token = 'token';
  154. $uid = 'user';
  155. $user = 'User';
  156. $password = 'passme';
  157. $name = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  158. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  159. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  160. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12';
  161. $type = IToken::PERMANENT_TOKEN;
  162. $actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER);
  163. $this->mapper->method('getTokenByUser')
  164. ->with('user')
  165. ->willReturn([$actual]);
  166. $newpass = 'newpass';
  167. $this->mapper->expects($this->once())
  168. ->method('update')
  169. ->with($this->callback(function ($token) use ($newpass) {
  170. return $newpass === $this->tokenProvider->getPassword($token, 'token');
  171. }));
  172. $this->tokenProvider->setPassword($actual, $token, $newpass);
  173. $this->assertSame($newpass, $this->tokenProvider->getPassword($actual, 'token'));
  174. }
  175. public function testSetPasswordInvalidToken() {
  176. $this->expectException(\OC\Authentication\Exceptions\InvalidTokenException::class);
  177. $token = $this->createMock(IToken::class);
  178. $tokenId = 'token123';
  179. $password = '123456';
  180. $this->tokenProvider->setPassword($token, $tokenId, $password);
  181. }
  182. public function testInvalidateToken() {
  183. $this->mapper->expects($this->once())
  184. ->method('invalidate')
  185. ->with(hash('sha512', 'token7'.'1f4h9s'));
  186. $this->tokenProvider->invalidateToken('token7');
  187. }
  188. public function testInvaildateTokenById() {
  189. $id = 123;
  190. $this->mapper->expects($this->once())
  191. ->method('deleteById')
  192. ->with('uid', $id);
  193. $this->tokenProvider->invalidateTokenById('uid', $id);
  194. }
  195. public function testInvalidateOldTokens() {
  196. $defaultSessionLifetime = 60 * 60 * 24;
  197. $defaultRememberMeLifetime = 60 * 60 * 24 * 15;
  198. $this->config->expects($this->exactly(2))
  199. ->method('getSystemValue')
  200. ->willReturnMap([
  201. ['session_lifetime', $defaultSessionLifetime, 150],
  202. ['remember_login_cookie_lifetime', $defaultRememberMeLifetime, 300],
  203. ]);
  204. $this->mapper->expects($this->at(0))
  205. ->method('invalidateOld')
  206. ->with($this->time - 150);
  207. $this->mapper->expects($this->at(1))
  208. ->method('invalidateOld')
  209. ->with($this->time - 300);
  210. $this->tokenProvider->invalidateOldTokens();
  211. }
  212. public function testRenewSessionTokenWithoutPassword() {
  213. $token = 'oldId';
  214. $uid = 'user';
  215. $user = 'User';
  216. $password = null;
  217. $name = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  218. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  219. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  220. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12';
  221. $type = IToken::PERMANENT_TOKEN;
  222. $oldToken = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER);
  223. $this->mapper
  224. ->expects($this->at(0))
  225. ->method('getToken')
  226. ->with(hash('sha512', 'oldId' . '1f4h9s'))
  227. ->willReturn($oldToken);
  228. $this->mapper
  229. ->expects($this->at(1))
  230. ->method('insert')
  231. ->with($this->callback(function (PublicKeyToken $token) use ($user, $uid, $name) {
  232. return $token->getUID() === $uid &&
  233. $token->getLoginName() === $user &&
  234. $token->getName() === $name &&
  235. $token->getType() === IToken::DO_NOT_REMEMBER &&
  236. $token->getLastActivity() === $this->time &&
  237. $token->getPassword() === null;
  238. }));
  239. $this->mapper
  240. ->expects($this->at(2))
  241. ->method('delete')
  242. ->with($this->callback(function ($token) use ($oldToken) {
  243. return $token === $oldToken;
  244. }));
  245. $this->tokenProvider->renewSessionToken('oldId', 'newId');
  246. }
  247. public function testRenewSessionTokenWithPassword() {
  248. $token = 'oldId';
  249. $uid = 'user';
  250. $user = 'User';
  251. $password = 'password';
  252. $name = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  253. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  254. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  255. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12';
  256. $type = IToken::PERMANENT_TOKEN;
  257. $oldToken = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER);
  258. $this->mapper
  259. ->expects($this->at(0))
  260. ->method('getToken')
  261. ->with(hash('sha512', 'oldId' . '1f4h9s'))
  262. ->willReturn($oldToken);
  263. $this->mapper
  264. ->expects($this->at(1))
  265. ->method('insert')
  266. ->with($this->callback(function (PublicKeyToken $token) use ($user, $uid, $name) {
  267. return $token->getUID() === $uid &&
  268. $token->getLoginName() === $user &&
  269. $token->getName() === $name &&
  270. $token->getType() === IToken::DO_NOT_REMEMBER &&
  271. $token->getLastActivity() === $this->time &&
  272. $token->getPassword() !== null &&
  273. $this->tokenProvider->getPassword($token, 'newId') === 'password';
  274. }));
  275. $this->mapper
  276. ->expects($this->at(2))
  277. ->method('delete')
  278. ->with($this->callback(function ($token) use ($oldToken) {
  279. return $token === $oldToken;
  280. }));
  281. $this->tokenProvider->renewSessionToken('oldId', 'newId');
  282. }
  283. public function testGetToken() {
  284. $token = new PublicKeyToken();
  285. $this->config->method('getSystemValue')
  286. ->with('secret')
  287. ->willReturn('mysecret');
  288. $this->mapper->method('getToken')
  289. ->with(
  290. $this->callback(function (string $token) {
  291. return hash('sha512', 'unhashedToken'.'1f4h9s') === $token;
  292. })
  293. )->willReturn($token);
  294. $this->assertSame($token, $this->tokenProvider->getToken('unhashedToken'));
  295. }
  296. public function testGetInvalidToken() {
  297. $this->expectException(InvalidTokenException::class);
  298. $this->mapper->method('getToken')
  299. ->with(
  300. $this->callback(function (string $token) {
  301. return hash('sha512', 'unhashedToken'.'1f4h9s') === $token;
  302. })
  303. )->willThrowException(new DoesNotExistException('nope'));
  304. $this->tokenProvider->getToken('unhashedToken');
  305. }
  306. public function testGetExpiredToken() {
  307. $token = 'token';
  308. $uid = 'user';
  309. $user = 'User';
  310. $password = 'passme';
  311. $name = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  312. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  313. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  314. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12';
  315. $type = IToken::PERMANENT_TOKEN;
  316. $actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER);
  317. $actual->setExpires(42);
  318. $this->mapper->method('getToken')
  319. ->with(
  320. $this->callback(function (string $token) {
  321. return hash('sha512', 'token'.'1f4h9s') === $token;
  322. })
  323. )->willReturn($actual);
  324. try {
  325. $this->tokenProvider->getToken('token');
  326. $this->fail();
  327. } catch (ExpiredTokenException $e) {
  328. $this->assertSame($actual, $e->getToken());
  329. }
  330. }
  331. public function testGetTokenById() {
  332. $token = $this->createMock(PublicKeyToken::class);
  333. $this->mapper->expects($this->once())
  334. ->method('getTokenById')
  335. ->with($this->equalTo(42))
  336. ->willReturn($token);
  337. $this->assertSame($token, $this->tokenProvider->getTokenById(42));
  338. }
  339. public function testGetInvalidTokenById() {
  340. $this->expectException(InvalidTokenException::class);
  341. $this->mapper->expects($this->once())
  342. ->method('getTokenById')
  343. ->with($this->equalTo(42))
  344. ->willThrowException(new DoesNotExistException('nope'));
  345. $this->tokenProvider->getTokenById(42);
  346. }
  347. public function testGetExpiredTokenById() {
  348. $token = new PublicKeyToken();
  349. $token->setExpires(42);
  350. $this->mapper->expects($this->once())
  351. ->method('getTokenById')
  352. ->with($this->equalTo(42))
  353. ->willReturn($token);
  354. try {
  355. $this->tokenProvider->getTokenById(42);
  356. $this->fail();
  357. } catch (ExpiredTokenException $e) {
  358. $this->assertSame($token, $e->getToken());
  359. }
  360. }
  361. public function testRotate() {
  362. $token = 'oldtoken';
  363. $uid = 'user';
  364. $user = 'User';
  365. $password = 'password';
  366. $name = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  367. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  368. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  369. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12';
  370. $type = IToken::PERMANENT_TOKEN;
  371. $actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER);
  372. $new = $this->tokenProvider->rotate($actual, 'oldtoken', 'newtoken');
  373. $this->assertSame('password', $this->tokenProvider->getPassword($new, 'newtoken'));
  374. }
  375. public function testRotateNoPassword() {
  376. $token = 'oldtoken';
  377. $uid = 'user';
  378. $user = 'User';
  379. $password = null;
  380. $name = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  381. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  382. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
  383. . 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12';
  384. $type = IToken::PERMANENT_TOKEN;
  385. $actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER);
  386. $oldPrivate = $actual->getPrivateKey();
  387. $new = $this->tokenProvider->rotate($actual, 'oldtoken', 'newtoken');
  388. $newPrivate = $new->getPrivateKey();
  389. $this->assertNotSame($newPrivate, $oldPrivate);
  390. $this->assertNull($new->getPassword());
  391. }
  392. public function testConvertToken() {
  393. $defaultToken = new DefaultToken();
  394. $defaultToken->setId(42);
  395. $defaultToken->setPassword('oldPass');
  396. $defaultToken->setExpires(1337);
  397. $defaultToken->setToken('oldToken');
  398. $defaultToken->setUid('uid');
  399. $defaultToken->setLoginName('loginName');
  400. $defaultToken->setLastActivity(999);
  401. $defaultToken->setName('name');
  402. $defaultToken->setRemember(IToken::REMEMBER);
  403. $defaultToken->setType(IToken::PERMANENT_TOKEN);
  404. $this->mapper->expects($this->once())
  405. ->method('update')
  406. ->willReturnArgument(0);
  407. $newToken = $this->tokenProvider->convertToken($defaultToken, 'newToken', 'newPassword');
  408. $this->assertSame(42, $newToken->getId());
  409. $this->assertSame('newPassword', $this->tokenProvider->getPassword($newToken, 'newToken'));
  410. $this->assertSame(1337, $newToken->getExpires());
  411. $this->assertSame('uid', $newToken->getUID());
  412. $this->assertSame('loginName', $newToken->getLoginName());
  413. $this->assertSame(1313131, $newToken->getLastActivity());
  414. $this->assertSame(1313131, $newToken->getLastCheck());
  415. $this->assertSame('name', $newToken->getName());
  416. $this->assertSame(IToken::REMEMBER, $newToken->getRemember());
  417. $this->assertSame(IToken::PERMANENT_TOKEN, $newToken->getType());
  418. }
  419. public function testMarkPasswordInvalidInvalidToken() {
  420. $token = $this->createMock(DefaultToken::class);
  421. $this->expectException(InvalidTokenException::class);
  422. $this->tokenProvider->markPasswordInvalid($token, 'tokenId');
  423. }
  424. public function testMarkPasswordInvalid() {
  425. $token = $this->createMock(PublicKeyToken::class);
  426. $token->expects($this->once())
  427. ->method('setPasswordInvalid')
  428. ->with(true);
  429. $this->mapper->expects($this->once())
  430. ->method('update')
  431. ->with($token);
  432. $this->tokenProvider->markPasswordInvalid($token, 'tokenId');
  433. }
  434. public function testUpdatePasswords() {
  435. $uid = 'myUID';
  436. $token1 = $this->tokenProvider->generateToken(
  437. 'foo',
  438. $uid,
  439. $uid,
  440. 'bar',
  441. 'random1',
  442. IToken::PERMANENT_TOKEN,
  443. IToken::REMEMBER);
  444. $token2 = $this->tokenProvider->generateToken(
  445. 'foobar',
  446. $uid,
  447. $uid,
  448. 'bar',
  449. 'random2',
  450. IToken::PERMANENT_TOKEN,
  451. IToken::REMEMBER);
  452. $this->mapper->expects($this->once())
  453. ->method('hasExpiredTokens')
  454. ->with($uid)
  455. ->willReturn(true);
  456. $this->mapper->expects($this->once())
  457. ->method('getTokenByUser')
  458. ->with($uid)
  459. ->willReturn([$token1, $token2]);
  460. $this->mapper->expects($this->exactly(2))
  461. ->method('update')
  462. ->with($this->callback(function (PublicKeyToken $t) use ($token1, $token2) {
  463. return $t === $token1 || $t === $token2;
  464. }));
  465. $this->tokenProvider->updatePasswords($uid, 'bar2');
  466. }
  467. public function testUpdatePasswordsNotRequired() {
  468. $uid = 'myUID';
  469. $this->mapper->expects($this->once())
  470. ->method('hasExpiredTokens')
  471. ->with($uid)
  472. ->willReturn(false);
  473. $this->mapper->expects($this->never())
  474. ->method('getTokenByUser');
  475. $this->mapper->expects($this->never())
  476. ->method('update');
  477. $this->tokenProvider->updatePasswords($uid, 'bar2');
  478. }
  479. }