From 0fdb59010a2ebfa7805bbf73c019a3cf2b37fe3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 24 Aug 2026 10:14:45 +0200 Subject: [PATCH] fix(2fa): Add missing BruteForceProtection attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- core/Controller/TwoFactorChallengeController.php | 6 +++++- tests/Core/Controller/TwoFactorChallengeControllerTest.php | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/Controller/TwoFactorChallengeController.php b/core/Controller/TwoFactorChallengeController.php index 46479639afa02..f6262aaa8b332 100644 --- a/core/Controller/TwoFactorChallengeController.php +++ b/core/Controller/TwoFactorChallengeController.php @@ -29,6 +29,7 @@ use OC\Authentication\TwoFactorAuth\Manager; use OC_User; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\Attribute\BruteForceProtection; use OCP\AppFramework\Http\Attribute\FrontpageRoute; use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\Attribute\UseSession; @@ -178,6 +179,7 @@ public function showChallenge($challengeProviderId, $redirect_url) { */ #[UseSession] #[FrontpageRoute(verb: 'POST', url: '/login/challenge/{challengeProviderId}')] + #[BruteForceProtection(action: 'solveChallenge')] public function solveChallenge($challengeProviderId, $challenge, $redirect_url = null) { $user = $this->userSession->getUser(); $provider = $this->twoFactorManager->getProvider($user, $challengeProviderId); @@ -205,10 +207,12 @@ public function solveChallenge($challengeProviderId, $challenge, $redirect_url = $uid = $user->getUID(); $this->logger->warning("Two-factor challenge failed: $uid (Remote IP: $ip)"); $this->session->set('two_factor_auth_error', true); - return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.showChallenge', [ + $response = new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.showChallenge', [ 'challengeProviderId' => $provider->getId(), 'redirect_url' => $redirect_url, ])); + $response->throttle(['user' => $uid, 'provider' => $challengeProviderId]); + return $response; } /** diff --git a/tests/Core/Controller/TwoFactorChallengeControllerTest.php b/tests/Core/Controller/TwoFactorChallengeControllerTest.php index c937b92599793..103c026471874 100644 --- a/tests/Core/Controller/TwoFactorChallengeControllerTest.php +++ b/tests/Core/Controller/TwoFactorChallengeControllerTest.php @@ -267,6 +267,7 @@ public function testSolveChallengeInvalidProvider() { public function testSolveInvalidChallenge() { $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn('myuser'); $provider = $this->createMock(IProvider::class); $this->userSession->expects($this->once()) @@ -296,11 +297,13 @@ public function testSolveInvalidChallenge() { ->willReturn('myprovider'); $expected = new RedirectResponse('files/index/url'); + $expected->throttle(['user' => 'myuser', 'provider' => 'myprovider']); $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', '/url')); } public function testSolveChallengeTwoFactorException() { $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn('myuser'); $provider = $this->createMock(IProvider::class); $exception = new TwoFactorException("2FA failed"); @@ -334,6 +337,7 @@ public function testSolveChallengeTwoFactorException() { ->willReturn('myprovider'); $expected = new RedirectResponse('files/index/url'); + $expected->throttle(['user' => 'myuser', 'provider' => 'myprovider']); $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', '/url')); }