aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/oauth2/lib/Controller/OauthApiController.php22
-rw-r--r--apps/oauth2/tests/Controller/OauthApiControllerTest.php6
-rw-r--r--core/Command/User/Add.php10
-rw-r--r--core/Command/User/AddAppPassword.php19
-rw-r--r--core/Command/User/Delete.php11
-rw-r--r--core/Command/User/Disable.php7
-rw-r--r--core/Command/User/Enable.php7
-rw-r--r--core/Command/User/Info.php10
-rw-r--r--core/Command/User/LastSeen.php7
-rw-r--r--core/Command/User/ListCommand.php11
-rw-r--r--core/Command/User/Report.php11
-rw-r--r--core/Command/User/ResetPassword.php10
-rw-r--r--core/Command/User/Setting.php10
-rw-r--r--package-lock.json14
-rw-r--r--package.json2
15 files changed, 73 insertions, 84 deletions
diff --git a/apps/oauth2/lib/Controller/OauthApiController.php b/apps/oauth2/lib/Controller/OauthApiController.php
index badafd3bb77..e07a2c2de15 100644
--- a/apps/oauth2/lib/Controller/OauthApiController.php
+++ b/apps/oauth2/lib/Controller/OauthApiController.php
@@ -64,6 +64,7 @@ class OauthApiController extends Controller {
/**
* @PublicPage
* @NoCSRFRequired
+ * @BruteForceProtection(action=oauth2GetToken)
*
* @param string $grant_type
* @param string $code
@@ -76,9 +77,11 @@ class OauthApiController extends Controller {
// We only handle two types
if ($grant_type !== 'authorization_code' && $grant_type !== 'refresh_token') {
- return new JSONResponse([
+ $response = new JSONResponse([
'error' => 'invalid_grant',
], Http::STATUS_BAD_REQUEST);
+ $response->throttle(['invalid_grant' => $grant_type]);
+ return $response;
}
// We handle the initial and refresh tokens the same way
@@ -89,17 +92,21 @@ class OauthApiController extends Controller {
try {
$accessToken = $this->accessTokenMapper->getByCode($code);
} catch (AccessTokenNotFoundException $e) {
- return new JSONResponse([
+ $response = new JSONResponse([
'error' => 'invalid_request',
], Http::STATUS_BAD_REQUEST);
+ $response->throttle(['invalid_request' => 'token not found', 'code' => $code]);
+ return $response;
}
try {
$client = $this->clientMapper->getByUid($accessToken->getClientId());
} catch (ClientNotFoundException $e) {
- return new JSONResponse([
+ $response = new JSONResponse([
'error' => 'invalid_request',
], Http::STATUS_BAD_REQUEST);
+ $response->throttle(['invalid_request' => 'client not found', 'client_id' => $accessToken->getClientId()]);
+ return $response;
}
if (isset($this->request->server['PHP_AUTH_USER'])) {
@@ -111,15 +118,18 @@ class OauthApiController extends Controller {
$storedClientSecret = $this->crypto->decrypt($client->getSecret());
} catch (\Exception $e) {
$this->logger->error('OAuth client secret decryption error', ['exception' => $e]);
+ // we don't throttle here because it might not be a bruteforce attack
return new JSONResponse([
'error' => 'invalid_client',
], Http::STATUS_BAD_REQUEST);
}
// The client id and secret must match. Else we don't provide an access token!
if ($client->getClientIdentifier() !== $client_id || $storedClientSecret !== $client_secret) {
- return new JSONResponse([
+ $response = new JSONResponse([
'error' => 'invalid_client',
], Http::STATUS_BAD_REQUEST);
+ $response->throttle(['invalid_client' => 'client ID or secret does not match']);
+ return $response;
}
$decryptedToken = $this->crypto->decrypt($accessToken->getEncryptedToken(), $code);
@@ -132,9 +142,11 @@ class OauthApiController extends Controller {
} catch (InvalidTokenException $e) {
//We can't do anything...
$this->accessTokenMapper->delete($accessToken);
- return new JSONResponse([
+ $response = new JSONResponse([
'error' => 'invalid_request',
], Http::STATUS_BAD_REQUEST);
+ $response->throttle(['invalid_request' => 'token is invalid']);
+ return $response;
}
// Rotate the apptoken (so the old one becomes invalid basically)
diff --git a/apps/oauth2/tests/Controller/OauthApiControllerTest.php b/apps/oauth2/tests/Controller/OauthApiControllerTest.php
index eb9311dbbc7..c65302532a9 100644
--- a/apps/oauth2/tests/Controller/OauthApiControllerTest.php
+++ b/apps/oauth2/tests/Controller/OauthApiControllerTest.php
@@ -104,6 +104,7 @@ class OauthApiControllerTest extends TestCase {
$expected = new JSONResponse([
'error' => 'invalid_grant',
], Http::STATUS_BAD_REQUEST);
+ $expected->throttle(['invalid_grant' => 'foo']);
$this->assertEquals($expected, $this->oauthApiController->getToken('foo', null, null, null, null));
}
@@ -112,6 +113,7 @@ class OauthApiControllerTest extends TestCase {
$expected = new JSONResponse([
'error' => 'invalid_request',
], Http::STATUS_BAD_REQUEST);
+ $expected->throttle(['invalid_request' => 'token not found', 'code' => 'invalidcode']);
$this->accessTokenMapper->method('getByCode')
->with('invalidcode')
@@ -124,6 +126,7 @@ class OauthApiControllerTest extends TestCase {
$expected = new JSONResponse([
'error' => 'invalid_request',
], Http::STATUS_BAD_REQUEST);
+ $expected->throttle(['invalid_request' => 'token not found', 'code' => 'invalidrefresh']);
$this->accessTokenMapper->method('getByCode')
->with('invalidrefresh')
@@ -136,6 +139,7 @@ class OauthApiControllerTest extends TestCase {
$expected = new JSONResponse([
'error' => 'invalid_request',
], Http::STATUS_BAD_REQUEST);
+ $expected->throttle(['invalid_request' => 'client not found', 'client_id' => 42]);
$accessToken = new AccessToken();
$accessToken->setClientId(42);
@@ -169,6 +173,7 @@ class OauthApiControllerTest extends TestCase {
$expected = new JSONResponse([
'error' => 'invalid_client',
], Http::STATUS_BAD_REQUEST);
+ $expected->throttle(['invalid_client' => 'client ID or secret does not match']);
$accessToken = new AccessToken();
$accessToken->setClientId(42);
@@ -191,6 +196,7 @@ class OauthApiControllerTest extends TestCase {
$expected = new JSONResponse([
'error' => 'invalid_request',
], Http::STATUS_BAD_REQUEST);
+ $expected->throttle(['invalid_request' => 'token is invalid']);
$accessToken = new AccessToken();
$accessToken->setClientId(42);
diff --git a/core/Command/User/Add.php b/core/Command/User/Add.php
index 24d11fbee6e..5e8ab92070d 100644
--- a/core/Command/User/Add.php
+++ b/core/Command/User/Add.php
@@ -39,13 +39,11 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
class Add extends Command {
- protected IUserManager $userManager;
- protected IGroupManager $groupManager;
-
- public function __construct(IUserManager $userManager, IGroupManager $groupManager) {
+ public function __construct(
+ protected IUserManager $userManager,
+ protected IGroupManager $groupManager,
+ ) {
parent::__construct();
- $this->userManager = $userManager;
- $this->groupManager = $groupManager;
}
protected function configure() {
diff --git a/core/Command/User/AddAppPassword.php b/core/Command/User/AddAppPassword.php
index ec39cdc974e..8c506c8510e 100644
--- a/core/Command/User/AddAppPassword.php
+++ b/core/Command/User/AddAppPassword.php
@@ -41,19 +41,12 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
class AddAppPassword extends Command {
- protected IUserManager $userManager;
- protected IProvider $tokenProvider;
- private ISecureRandom $random;
- private IEventDispatcher $eventDispatcher;
-
- public function __construct(IUserManager $userManager,
- IProvider $tokenProvider,
- ISecureRandom $random,
- IEventDispatcher $eventDispatcher) {
- $this->tokenProvider = $tokenProvider;
- $this->userManager = $userManager;
- $this->random = $random;
- $this->eventDispatcher = $eventDispatcher;
+ public function __construct(
+ protected IUserManager $userManager,
+ protected IProvider $tokenProvider,
+ private ISecureRandom $random,
+ private IEventDispatcher $eventDispatcher,
+ ) {
parent::__construct();
}
diff --git a/core/Command/User/Delete.php b/core/Command/User/Delete.php
index 9624f04fa18..94390a3f070 100644
--- a/core/Command/User/Delete.php
+++ b/core/Command/User/Delete.php
@@ -33,14 +33,9 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Delete extends Base {
- /** @var IUserManager */
- protected $userManager;
-
- /**
- * @param IUserManager $userManager
- */
- public function __construct(IUserManager $userManager) {
- $this->userManager = $userManager;
+ public function __construct(
+ protected IUserManager $userManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/User/Disable.php b/core/Command/User/Disable.php
index bc819f39e1d..3fdf6220f45 100644
--- a/core/Command/User/Disable.php
+++ b/core/Command/User/Disable.php
@@ -32,10 +32,9 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Disable extends Base {
- protected IUserManager $userManager;
-
- public function __construct(IUserManager $userManager) {
- $this->userManager = $userManager;
+ public function __construct(
+ protected IUserManager $userManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/User/Enable.php b/core/Command/User/Enable.php
index f4e16eec4af..2055bd30cec 100644
--- a/core/Command/User/Enable.php
+++ b/core/Command/User/Enable.php
@@ -32,10 +32,9 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Enable extends Base {
- protected IUserManager $userManager;
-
- public function __construct(IUserManager $userManager) {
- $this->userManager = $userManager;
+ public function __construct(
+ protected IUserManager $userManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/User/Info.php b/core/Command/User/Info.php
index 1e89a8d0911..a8fb62099e2 100644
--- a/core/Command/User/Info.php
+++ b/core/Command/User/Info.php
@@ -35,12 +35,10 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class Info extends Base {
- protected IUserManager $userManager;
- protected IGroupManager $groupManager;
-
- public function __construct(IUserManager $userManager, IGroupManager $groupManager) {
- $this->userManager = $userManager;
- $this->groupManager = $groupManager;
+ public function __construct(
+ protected IUserManager $userManager,
+ protected IGroupManager $groupManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/User/LastSeen.php b/core/Command/User/LastSeen.php
index 5ea6c64d249..90ddb6992d9 100644
--- a/core/Command/User/LastSeen.php
+++ b/core/Command/User/LastSeen.php
@@ -34,10 +34,9 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class LastSeen extends Base {
- protected IUserManager $userManager;
-
- public function __construct(IUserManager $userManager) {
- $this->userManager = $userManager;
+ public function __construct(
+ protected IUserManager $userManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/User/ListCommand.php b/core/Command/User/ListCommand.php
index bf4bf7f030e..f25d6c2dae9 100644
--- a/core/Command/User/ListCommand.php
+++ b/core/Command/User/ListCommand.php
@@ -33,13 +33,10 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class ListCommand extends Base {
- protected IUserManager $userManager;
- protected IGroupManager $groupManager;
-
- public function __construct(IUserManager $userManager,
- IGroupManager $groupManager) {
- $this->userManager = $userManager;
- $this->groupManager = $groupManager;
+ public function __construct(
+ protected IUserManager $userManager,
+ protected IGroupManager $groupManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/User/Report.php b/core/Command/User/Report.php
index e080a617258..74ab5c29cc1 100644
--- a/core/Command/User/Report.php
+++ b/core/Command/User/Report.php
@@ -41,13 +41,10 @@ use Symfony\Component\Console\Output\OutputInterface;
class Report extends Command {
public const DEFAULT_COUNT_DIRS_MAX_USERS = 500;
- protected IUserManager $userManager;
- private IConfig $config;
-
- public function __construct(IUserManager $userManager,
- IConfig $config) {
- $this->userManager = $userManager;
- $this->config = $config;
+ public function __construct(
+ protected IUserManager $userManager,
+ private IConfig $config,
+ ) {
parent::__construct();
}
diff --git a/core/Command/User/ResetPassword.php b/core/Command/User/ResetPassword.php
index 294cea38b71..6719f893be3 100644
--- a/core/Command/User/ResetPassword.php
+++ b/core/Command/User/ResetPassword.php
@@ -41,13 +41,11 @@ use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Question\Question;
class ResetPassword extends Base {
- protected IUserManager $userManager;
- private IAppManager $appManager;
-
- public function __construct(IUserManager $userManager, IAppManager $appManager) {
+ public function __construct(
+ protected IUserManager $userManager,
+ private IAppManager $appManager,
+ ) {
parent::__construct();
- $this->userManager = $userManager;
- $this->appManager = $appManager;
}
protected function configure() {
diff --git a/core/Command/User/Setting.php b/core/Command/User/Setting.php
index fac5c3c976c..8a8736fdaa2 100644
--- a/core/Command/User/Setting.php
+++ b/core/Command/User/Setting.php
@@ -36,13 +36,11 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class Setting extends Base {
- protected IUserManager $userManager;
- protected IConfig $config;
-
- public function __construct(IUserManager $userManager, IConfig $config) {
+ public function __construct(
+ protected IUserManager $userManager,
+ protected IConfig $config,
+ ) {
parent::__construct();
- $this->userManager = $userManager;
- $this->config = $config;
}
protected function configure() {
diff --git a/package-lock.json b/package-lock.json
index ad8f605141f..413174b1e53 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,7 +19,7 @@
"@nextcloud/capabilities": "^1.0.4",
"@nextcloud/dialogs": "^4.0.1",
"@nextcloud/event-bus": "^3.1.0",
- "@nextcloud/files": "^3.0.0-beta.9",
+ "@nextcloud/files": "^3.0.0-beta.10",
"@nextcloud/initial-state": "^2.0.0",
"@nextcloud/l10n": "^2.1.0",
"@nextcloud/logger": "^2.5.0",
@@ -3429,9 +3429,9 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/@nextcloud/files": {
- "version": "3.0.0-beta.9",
- "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.0.0-beta.9.tgz",
- "integrity": "sha512-K4k8wmxNmIeJz5VmLzGiYH9wc6rv0i9BcVOL9xuSHPwf/ukJZzw/hKHnE1ohBzIKfCZUS619dsa2hI/OjRa3Lg==",
+ "version": "3.0.0-beta.10",
+ "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.0.0-beta.10.tgz",
+ "integrity": "sha512-cAh2HWkFgktub/GW07qx/kYz9nR2E/D+Zk/qXF8JW7BL/+gNy4/wOJ7mfDisUZy0gCZKZTV0v5wtEkIHwNdTyA==",
"dependencies": {
"@nextcloud/auth": "^2.0.0",
"@nextcloud/l10n": "^2.1.0",
@@ -26595,9 +26595,9 @@
}
},
"@nextcloud/files": {
- "version": "3.0.0-beta.9",
- "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.0.0-beta.9.tgz",
- "integrity": "sha512-K4k8wmxNmIeJz5VmLzGiYH9wc6rv0i9BcVOL9xuSHPwf/ukJZzw/hKHnE1ohBzIKfCZUS619dsa2hI/OjRa3Lg==",
+ "version": "3.0.0-beta.10",
+ "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.0.0-beta.10.tgz",
+ "integrity": "sha512-cAh2HWkFgktub/GW07qx/kYz9nR2E/D+Zk/qXF8JW7BL/+gNy4/wOJ7mfDisUZy0gCZKZTV0v5wtEkIHwNdTyA==",
"requires": {
"@nextcloud/auth": "^2.0.0",
"@nextcloud/l10n": "^2.1.0",
diff --git a/package.json b/package.json
index 6f771a0f097..e96e0fba95c 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,7 @@
"@nextcloud/capabilities": "^1.0.4",
"@nextcloud/dialogs": "^4.0.1",
"@nextcloud/event-bus": "^3.1.0",
- "@nextcloud/files": "^3.0.0-beta.9",
+ "@nextcloud/files": "^3.0.0-beta.10",
"@nextcloud/initial-state": "^2.0.0",
"@nextcloud/l10n": "^2.1.0",
"@nextcloud/logger": "^2.5.0",