TwoFactorCommandTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. <?php
  2. /**
  3. * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
  4. *
  5. * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
  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. declare(strict_types=1);
  23. namespace Test\Authentication\Login;
  24. use OC\Authentication\Login\TwoFactorCommand;
  25. use OC\Authentication\TwoFactorAuth\Manager;
  26. use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor;
  27. use OC\Authentication\TwoFactorAuth\ProviderSet;
  28. use OCP\Authentication\TwoFactorAuth\IActivatableAtLogin;
  29. use OCP\Authentication\TwoFactorAuth\IProvider as ITwoFactorAuthProvider;
  30. use OCP\IURLGenerator;
  31. use PHPUnit\Framework\MockObject\MockObject;
  32. class TwoFactorCommandTest extends ALoginCommandTest {
  33. /** @var Manager|MockObject */
  34. private $twoFactorManager;
  35. /** @var MandatoryTwoFactor|MockObject */
  36. private $mandatoryTwoFactor;
  37. /** @var IURLGenerator|MockObject */
  38. private $urlGenerator;
  39. protected function setUp(): void {
  40. parent::setUp();
  41. $this->twoFactorManager = $this->createMock(Manager::class);
  42. $this->mandatoryTwoFactor = $this->createMock(MandatoryTwoFactor::class);
  43. $this->urlGenerator = $this->createMock(IURLGenerator::class);
  44. $this->cmd = new TwoFactorCommand(
  45. $this->twoFactorManager,
  46. $this->mandatoryTwoFactor,
  47. $this->urlGenerator
  48. );
  49. }
  50. public function testNotTwoFactorAuthenticated() {
  51. $data = $this->getLoggedInLoginData();
  52. $this->twoFactorManager->expects($this->once())
  53. ->method('isTwoFactorAuthenticated')
  54. ->willReturn(false);
  55. $this->twoFactorManager->expects($this->never())
  56. ->method('prepareTwoFactorLogin');
  57. $result = $this->cmd->process($data);
  58. $this->assertTrue($result->isSuccess());
  59. }
  60. public function testProcessOneActiveProvider() {
  61. $data = $this->getLoggedInLoginData();
  62. $this->twoFactorManager->expects($this->once())
  63. ->method('isTwoFactorAuthenticated')
  64. ->willReturn(true);
  65. $this->twoFactorManager->expects($this->once())
  66. ->method('prepareTwoFactorLogin')
  67. ->with(
  68. $this->user,
  69. $data->isRememberLogin()
  70. );
  71. $provider = $this->createMock(ITwoFactorAuthProvider::class);
  72. $this->twoFactorManager->expects($this->once())
  73. ->method('getProviderSet')
  74. ->willReturn(new ProviderSet([
  75. $provider,
  76. ], false));
  77. $this->twoFactorManager->expects($this->once())
  78. ->method('getLoginSetupProviders')
  79. ->with($this->user)
  80. ->willReturn([]);
  81. $this->mandatoryTwoFactor->expects($this->any())
  82. ->method('isEnforcedFor')
  83. ->with($this->user)
  84. ->willReturn(false);
  85. $provider->expects($this->once())
  86. ->method('getId')
  87. ->willReturn('test');
  88. $this->urlGenerator->expects($this->once())
  89. ->method('linkToRoute')
  90. ->with(
  91. 'core.TwoFactorChallenge.showChallenge',
  92. [
  93. 'challengeProviderId' => 'test'
  94. ]
  95. )
  96. ->willReturn('two/factor/url');
  97. $result = $this->cmd->process($data);
  98. $this->assertTrue($result->isSuccess());
  99. $this->assertEquals('two/factor/url', $result->getRedirectUrl());
  100. }
  101. public function testProcessMissingProviders() {
  102. $data = $this->getLoggedInLoginData();
  103. $this->twoFactorManager->expects($this->once())
  104. ->method('isTwoFactorAuthenticated')
  105. ->willReturn(true);
  106. $this->twoFactorManager->expects($this->once())
  107. ->method('prepareTwoFactorLogin')
  108. ->with(
  109. $this->user,
  110. $data->isRememberLogin()
  111. );
  112. $provider = $this->createMock(ITwoFactorAuthProvider::class);
  113. $provider->expects($this->once())
  114. ->method('getId')
  115. ->willReturn('test1');
  116. $this->twoFactorManager->expects($this->once())
  117. ->method('getProviderSet')
  118. ->willReturn(new ProviderSet([
  119. $provider,
  120. ], true));
  121. $this->twoFactorManager->expects($this->once())
  122. ->method('getLoginSetupProviders')
  123. ->with($this->user)
  124. ->willReturn([]);
  125. $this->mandatoryTwoFactor->expects($this->any())
  126. ->method('isEnforcedFor')
  127. ->with($this->user)
  128. ->willReturn(false);
  129. $this->urlGenerator->expects($this->once())
  130. ->method('linkToRoute')
  131. ->with(
  132. 'core.TwoFactorChallenge.selectChallenge'
  133. )
  134. ->willReturn('two/factor/url');
  135. $result = $this->cmd->process($data);
  136. $this->assertTrue($result->isSuccess());
  137. $this->assertEquals('two/factor/url', $result->getRedirectUrl());
  138. }
  139. public function testProcessTwoActiveProviders() {
  140. $data = $this->getLoggedInLoginData();
  141. $this->twoFactorManager->expects($this->once())
  142. ->method('isTwoFactorAuthenticated')
  143. ->willReturn(true);
  144. $this->twoFactorManager->expects($this->once())
  145. ->method('prepareTwoFactorLogin')
  146. ->with(
  147. $this->user,
  148. $data->isRememberLogin()
  149. );
  150. $provider1 = $this->createMock(ITwoFactorAuthProvider::class);
  151. $provider2 = $this->createMock(ITwoFactorAuthProvider::class);
  152. $provider1->expects($this->once())
  153. ->method('getId')
  154. ->willReturn('test1');
  155. $provider2->expects($this->once())
  156. ->method('getId')
  157. ->willReturn('test2');
  158. $this->twoFactorManager->expects($this->once())
  159. ->method('getProviderSet')
  160. ->willReturn(new ProviderSet([
  161. $provider1,
  162. $provider2,
  163. ], false));
  164. $this->twoFactorManager->expects($this->once())
  165. ->method('getLoginSetupProviders')
  166. ->with($this->user)
  167. ->willReturn([]);
  168. $this->mandatoryTwoFactor->expects($this->any())
  169. ->method('isEnforcedFor')
  170. ->with($this->user)
  171. ->willReturn(false);
  172. $this->urlGenerator->expects($this->once())
  173. ->method('linkToRoute')
  174. ->with(
  175. 'core.TwoFactorChallenge.selectChallenge'
  176. )
  177. ->willReturn('two/factor/url');
  178. $result = $this->cmd->process($data);
  179. $this->assertTrue($result->isSuccess());
  180. $this->assertEquals('two/factor/url', $result->getRedirectUrl());
  181. }
  182. public function testProcessFailingProviderAndEnforcedButNoSetupProviders() {
  183. $data = $this->getLoggedInLoginData();
  184. $this->twoFactorManager->expects($this->once())
  185. ->method('isTwoFactorAuthenticated')
  186. ->willReturn(true);
  187. $this->twoFactorManager->expects($this->once())
  188. ->method('prepareTwoFactorLogin')
  189. ->with(
  190. $this->user,
  191. $data->isRememberLogin()
  192. );
  193. $this->twoFactorManager->expects($this->once())
  194. ->method('getProviderSet')
  195. ->willReturn(new ProviderSet([], true));
  196. $this->twoFactorManager->expects($this->once())
  197. ->method('getLoginSetupProviders')
  198. ->with($this->user)
  199. ->willReturn([]);
  200. $this->mandatoryTwoFactor->expects($this->any())
  201. ->method('isEnforcedFor')
  202. ->with($this->user)
  203. ->willReturn(true);
  204. $this->urlGenerator->expects($this->once())
  205. ->method('linkToRoute')
  206. ->with(
  207. 'core.TwoFactorChallenge.selectChallenge'
  208. )
  209. ->willReturn('two/factor/url');
  210. $result = $this->cmd->process($data);
  211. $this->assertTrue($result->isSuccess());
  212. $this->assertEquals('two/factor/url', $result->getRedirectUrl());
  213. }
  214. public function testProcessFailingProviderAndEnforced() {
  215. $data = $this->getLoggedInLoginData();
  216. $this->twoFactorManager->expects($this->once())
  217. ->method('isTwoFactorAuthenticated')
  218. ->willReturn(true);
  219. $this->twoFactorManager->expects($this->once())
  220. ->method('prepareTwoFactorLogin')
  221. ->with(
  222. $this->user,
  223. $data->isRememberLogin()
  224. );
  225. $provider = $this->createMock(IActivatableAtLogin::class);
  226. $this->twoFactorManager->expects($this->once())
  227. ->method('getProviderSet')
  228. ->willReturn(new ProviderSet([
  229. $provider,
  230. ], true));
  231. $this->twoFactorManager->expects($this->once())
  232. ->method('getLoginSetupProviders')
  233. ->with($this->user)
  234. ->willReturn([]);
  235. $this->mandatoryTwoFactor->expects($this->any())
  236. ->method('isEnforcedFor')
  237. ->with($this->user)
  238. ->willReturn(true);
  239. $this->urlGenerator->expects($this->once())
  240. ->method('linkToRoute')
  241. ->with(
  242. 'core.TwoFactorChallenge.selectChallenge'
  243. )
  244. ->willReturn('two/factor/url');
  245. $result = $this->cmd->process($data);
  246. $this->assertTrue($result->isSuccess());
  247. $this->assertEquals('two/factor/url', $result->getRedirectUrl());
  248. }
  249. public function testProcessNoProvidersButEnforced() {
  250. $data = $this->getLoggedInLoginData();
  251. $this->twoFactorManager->expects($this->once())
  252. ->method('isTwoFactorAuthenticated')
  253. ->willReturn(true);
  254. $this->twoFactorManager->expects($this->once())
  255. ->method('prepareTwoFactorLogin')
  256. ->with(
  257. $this->user,
  258. $data->isRememberLogin()
  259. );
  260. $this->twoFactorManager->expects($this->once())
  261. ->method('getProviderSet')
  262. ->willReturn(new ProviderSet([], false));
  263. $this->twoFactorManager->expects($this->once())
  264. ->method('getLoginSetupProviders')
  265. ->with($this->user)
  266. ->willReturn([]);
  267. $this->mandatoryTwoFactor->expects($this->any())
  268. ->method('isEnforcedFor')
  269. ->with($this->user)
  270. ->willReturn(true);
  271. $this->urlGenerator->expects($this->once())
  272. ->method('linkToRoute')
  273. ->with(
  274. 'core.TwoFactorChallenge.selectChallenge'
  275. )
  276. ->willReturn('two/factor/url');
  277. $result = $this->cmd->process($data);
  278. $this->assertTrue($result->isSuccess());
  279. $this->assertEquals('two/factor/url', $result->getRedirectUrl());
  280. }
  281. public function testProcessWithRedirectUrl() {
  282. $data = $this->getLoggedInLoginDataWithRedirectUrl();
  283. $this->twoFactorManager->expects($this->once())
  284. ->method('isTwoFactorAuthenticated')
  285. ->willReturn(true);
  286. $this->twoFactorManager->expects($this->once())
  287. ->method('prepareTwoFactorLogin')
  288. ->with(
  289. $this->user,
  290. $data->isRememberLogin()
  291. );
  292. $provider = $this->createMock(ITwoFactorAuthProvider::class);
  293. $this->twoFactorManager->expects($this->once())
  294. ->method('getProviderSet')
  295. ->willReturn(new ProviderSet([
  296. $provider,
  297. ], false));
  298. $this->twoFactorManager->expects($this->once())
  299. ->method('getLoginSetupProviders')
  300. ->with($this->user)
  301. ->willReturn([]);
  302. $this->mandatoryTwoFactor->expects($this->any())
  303. ->method('isEnforcedFor')
  304. ->with($this->user)
  305. ->willReturn(false);
  306. $provider->expects($this->once())
  307. ->method('getId')
  308. ->willReturn('test');
  309. $this->urlGenerator->expects($this->once())
  310. ->method('linkToRoute')
  311. ->with(
  312. 'core.TwoFactorChallenge.showChallenge',
  313. [
  314. 'challengeProviderId' => 'test',
  315. 'redirect_url' => $this->redirectUrl,
  316. ]
  317. )
  318. ->willReturn('two/factor/url');
  319. $result = $this->cmd->process($data);
  320. $this->assertTrue($result->isSuccess());
  321. $this->assertEquals('two/factor/url', $result->getRedirectUrl());
  322. }
  323. }