aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Authentication
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/Authentication')
-rw-r--r--lib/private/Authentication/Events/ARemoteWipeEvent.php21
-rw-r--r--lib/private/Authentication/Events/AppPasswordCreatedEvent.php31
-rw-r--r--lib/private/Authentication/Events/LoginFailed.php21
-rw-r--r--lib/private/Authentication/Events/RemoteWipeFinished.php21
-rw-r--r--lib/private/Authentication/Events/RemoteWipeStarted.php21
-rw-r--r--lib/private/Authentication/Exceptions/ExpiredTokenException.php41
-rw-r--r--lib/private/Authentication/Exceptions/InvalidProviderException.php23
-rw-r--r--lib/private/Authentication/Exceptions/InvalidTokenException.php29
-rw-r--r--lib/private/Authentication/Exceptions/LoginRequiredException.php22
-rw-r--r--lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php22
-rw-r--r--lib/private/Authentication/Exceptions/PasswordlessTokenException.php22
-rw-r--r--lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php21
-rw-r--r--lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php22
-rw-r--r--lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php22
-rw-r--r--lib/private/Authentication/Exceptions/WipeTokenException.php41
-rw-r--r--lib/private/Authentication/Listeners/LoginFailedListener.php22
-rw-r--r--lib/private/Authentication/Listeners/RemoteWipeActivityListener.php24
-rw-r--r--lib/private/Authentication/Listeners/RemoteWipeEmailListener.php28
-rw-r--r--lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php26
-rw-r--r--lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php50
-rw-r--r--lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php21
-rw-r--r--lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php24
-rw-r--r--lib/private/Authentication/Listeners/UserDeletedWebAuthnCleanupListener.php22
-rw-r--r--lib/private/Authentication/Listeners/UserLoggedInListener.php22
-rw-r--r--lib/private/Authentication/Login/ALoginCommand.php21
-rw-r--r--lib/private/Authentication/Login/Chain.php96
-rw-r--r--lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php21
-rw-r--r--lib/private/Authentication/Login/CompleteLoginCommand.php21
-rw-r--r--lib/private/Authentication/Login/CreateSessionTokenCommand.php25
-rw-r--r--lib/private/Authentication/Login/EmailLoginCommand.php70
-rw-r--r--lib/private/Authentication/Login/FinishRememberedLoginCommand.php24
-rw-r--r--lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php30
-rw-r--r--lib/private/Authentication/Login/LoggedInCheckCommand.php25
-rw-r--r--lib/private/Authentication/Login/LoginData.php32
-rw-r--r--lib/private/Authentication/Login/LoginResult.php28
-rw-r--r--lib/private/Authentication/Login/PreLoginHookCommand.php22
-rw-r--r--lib/private/Authentication/Login/SetUserTimezoneCommand.php23
-rw-r--r--lib/private/Authentication/Login/TwoFactorCommand.php30
-rw-r--r--lib/private/Authentication/Login/UidLoginCommand.php21
-rw-r--r--lib/private/Authentication/Login/UpdateLastPasswordConfirmCommand.php21
-rw-r--r--lib/private/Authentication/Login/UserDisabledCheckCommand.php24
-rw-r--r--lib/private/Authentication/Login/WebAuthnChain.php39
-rw-r--r--lib/private/Authentication/Login/WebAuthnLoginCommand.php21
-rw-r--r--lib/private/Authentication/LoginCredentials/Credentials.php22
-rw-r--r--lib/private/Authentication/LoginCredentials/Store.php45
-rw-r--r--lib/private/Authentication/Notifications/Notifier.php28
-rw-r--r--lib/private/Authentication/Token/INamedToken.php22
-rw-r--r--lib/private/Authentication/Token/IProvider.php94
-rw-r--r--lib/private/Authentication/Token/IToken.php133
-rw-r--r--lib/private/Authentication/Token/IWipeableToken.php22
-rw-r--r--lib/private/Authentication/Token/Manager.php113
-rw-r--r--lib/private/Authentication/Token/PublicKeyToken.php57
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenMapper.php100
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenProvider.php407
-rw-r--r--lib/private/Authentication/Token/RemoteWipe.php39
-rw-r--r--lib/private/Authentication/Token/TokenCleanupJob.php21
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php88
-rw-r--r--lib/private/Authentication/TwoFactorAuth/EnforcementState.php25
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Manager.php98
-rw-r--r--lib/private/Authentication/TwoFactorAuth/MandatoryTwoFactor.php21
-rw-r--r--lib/private/Authentication/TwoFactorAuth/ProviderLoader.php54
-rw-r--r--lib/private/Authentication/TwoFactorAuth/ProviderManager.php21
-rw-r--r--lib/private/Authentication/TwoFactorAuth/ProviderSet.php23
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Registry.php30
-rw-r--r--lib/private/Authentication/WebAuthn/CredentialRepository.php32
-rw-r--r--lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialEntity.php33
-rw-r--r--lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialMapper.php22
-rw-r--r--lib/private/Authentication/WebAuthn/Manager.php92
68 files changed, 853 insertions, 2002 deletions
diff --git a/lib/private/Authentication/Events/ARemoteWipeEvent.php b/lib/private/Authentication/Events/ARemoteWipeEvent.php
index e36b7d1087b..ba1e93d26ae 100644
--- a/lib/private/Authentication/Events/ARemoteWipeEvent.php
+++ b/lib/private/Authentication/Events/ARemoteWipeEvent.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Events;
diff --git a/lib/private/Authentication/Events/AppPasswordCreatedEvent.php b/lib/private/Authentication/Events/AppPasswordCreatedEvent.php
index a90abd25026..bf502ade0cc 100644
--- a/lib/private/Authentication/Events/AppPasswordCreatedEvent.php
+++ b/lib/private/Authentication/Events/AppPasswordCreatedEvent.php
@@ -3,38 +3,19 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Events;
-use OC\Authentication\Token\IToken;
+use OCP\Authentication\Token\IToken;
use OCP\EventDispatcher\Event;
class AppPasswordCreatedEvent extends Event {
- /** @var IToken */
- private $token;
-
- public function __construct(IToken $token) {
+ public function __construct(
+ private IToken $token,
+ ) {
parent::__construct();
- $this->token = $token;
}
public function getToken(): IToken {
diff --git a/lib/private/Authentication/Events/LoginFailed.php b/lib/private/Authentication/Events/LoginFailed.php
index ef702e40a59..23eeaef87ad 100644
--- a/lib/private/Authentication/Events/LoginFailed.php
+++ b/lib/private/Authentication/Events/LoginFailed.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Events;
diff --git a/lib/private/Authentication/Events/RemoteWipeFinished.php b/lib/private/Authentication/Events/RemoteWipeFinished.php
index 10e72de096c..9704ebff3f5 100644
--- a/lib/private/Authentication/Events/RemoteWipeFinished.php
+++ b/lib/private/Authentication/Events/RemoteWipeFinished.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Events;
diff --git a/lib/private/Authentication/Events/RemoteWipeStarted.php b/lib/private/Authentication/Events/RemoteWipeStarted.php
index 273a319b1fb..ad0f72f0e09 100644
--- a/lib/private/Authentication/Events/RemoteWipeStarted.php
+++ b/lib/private/Authentication/Events/RemoteWipeStarted.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Events;
diff --git a/lib/private/Authentication/Exceptions/ExpiredTokenException.php b/lib/private/Authentication/Exceptions/ExpiredTokenException.php
index 0dc92b45920..eed2358d29d 100644
--- a/lib/private/Authentication/Exceptions/ExpiredTokenException.php
+++ b/lib/private/Authentication/Exceptions/ExpiredTokenException.php
@@ -3,41 +3,26 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Exceptions;
use OC\Authentication\Token\IToken;
-class ExpiredTokenException extends InvalidTokenException {
- /** @var IToken */
- private $token;
-
- public function __construct(IToken $token) {
- parent::__construct();
-
- $this->token = $token;
+/**
+ * @deprecated 28.0.0 use {@see \OCP\Authentication\Exceptions\ExpiredTokenException} instead
+ */
+class ExpiredTokenException extends \OCP\Authentication\Exceptions\ExpiredTokenException {
+ public function __construct(
+ IToken $token,
+ ) {
+ parent::__construct($token);
}
public function getToken(): IToken {
- return $this->token;
+ $token = parent::getToken();
+ /** @var IToken $token We know that we passed OC interface from constructor */
+ return $token;
}
}
diff --git a/lib/private/Authentication/Exceptions/InvalidProviderException.php b/lib/private/Authentication/Exceptions/InvalidProviderException.php
index 86b44e4d0e2..9dbf3a7782a 100644
--- a/lib/private/Authentication/Exceptions/InvalidProviderException.php
+++ b/lib/private/Authentication/Exceptions/InvalidProviderException.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Exceptions;
@@ -29,7 +12,7 @@ use Exception;
use Throwable;
class InvalidProviderException extends Exception {
- public function __construct(string $providerId, Throwable $previous = null) {
+ public function __construct(string $providerId, ?Throwable $previous = null) {
parent::__construct("The provider '$providerId' does not exist'", 0, $previous);
}
}
diff --git a/lib/private/Authentication/Exceptions/InvalidTokenException.php b/lib/private/Authentication/Exceptions/InvalidTokenException.php
index acaabff6b88..d23f767e69b 100644
--- a/lib/private/Authentication/Exceptions/InvalidTokenException.php
+++ b/lib/private/Authentication/Exceptions/InvalidTokenException.php
@@ -1,30 +1,15 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
-use Exception;
-
-class InvalidTokenException extends Exception {
+/**
+ * @deprecated 28.0.0 use OCP version instead
+ */
+class InvalidTokenException extends \OCP\Authentication\Exceptions\InvalidTokenException {
}
diff --git a/lib/private/Authentication/Exceptions/LoginRequiredException.php b/lib/private/Authentication/Exceptions/LoginRequiredException.php
index cc3e8636214..d18ec4f1fbf 100644
--- a/lib/private/Authentication/Exceptions/LoginRequiredException.php
+++ b/lib/private/Authentication/Exceptions/LoginRequiredException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php b/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php
index 28829390f70..ec833a5a3d0 100644
--- a/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php
+++ b/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/PasswordlessTokenException.php b/lib/private/Authentication/Exceptions/PasswordlessTokenException.php
index c974cc3d6fd..a11e9a5f8d5 100644
--- a/lib/private/Authentication/Exceptions/PasswordlessTokenException.php
+++ b/lib/private/Authentication/Exceptions/PasswordlessTokenException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php b/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php
index 7710673ce7c..aa331f31fd0 100644
--- a/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php
+++ b/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php b/lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php
index 9733c4547b4..8873b2c9f85 100644
--- a/lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php
+++ b/lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php b/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php
index 520372f3087..257f59772fc 100644
--- a/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php
+++ b/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Exceptions;
diff --git a/lib/private/Authentication/Exceptions/WipeTokenException.php b/lib/private/Authentication/Exceptions/WipeTokenException.php
index 1c60ab9da78..6bf0565434a 100644
--- a/lib/private/Authentication/Exceptions/WipeTokenException.php
+++ b/lib/private/Authentication/Exceptions/WipeTokenException.php
@@ -3,41 +3,26 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Exceptions;
use OC\Authentication\Token\IToken;
-class WipeTokenException extends InvalidTokenException {
- /** @var IToken */
- private $token;
-
- public function __construct(IToken $token) {
- parent::__construct();
-
- $this->token = $token;
+/**
+ * @deprecated 28.0.0 use {@see \OCP\Authentication\Exceptions\WipeTokenException} instead
+ */
+class WipeTokenException extends \OCP\Authentication\Exceptions\WipeTokenException {
+ public function __construct(
+ IToken $token,
+ ) {
+ parent::__construct($token);
}
public function getToken(): IToken {
- return $this->token;
+ $token = parent::getToken();
+ /** @var IToken $token We know that we passed OC interface from constructor */
+ return $token;
}
}
diff --git a/lib/private/Authentication/Listeners/LoginFailedListener.php b/lib/private/Authentication/Listeners/LoginFailedListener.php
index d2971e07b55..0358887bb86 100644
--- a/lib/private/Authentication/Listeners/LoginFailedListener.php
+++ b/lib/private/Authentication/Listeners/LoginFailedListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
diff --git a/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php b/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php
index edebb2a2641..457630eff27 100644
--- a/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php
+++ b/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -46,7 +28,7 @@ class RemoteWipeActivityListener implements IEventListener {
private $logger;
public function __construct(IActvityManager $activityManager,
- LoggerInterface $logger) {
+ LoggerInterface $logger) {
$this->activityManager = $activityManager;
$this->logger = $logger;
}
diff --git a/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php b/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php
index cba2b183589..96878c44123 100644
--- a/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php
+++ b/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -57,9 +39,9 @@ class RemoteWipeEmailListener implements IEventListener {
private $logger;
public function __construct(IMailer $mailer,
- IUserManager $userManager,
- IL10nFactory $l10nFactory,
- LoggerInterface $logger) {
+ IUserManager $userManager,
+ IL10nFactory $l10nFactory,
+ LoggerInterface $logger) {
$this->mailer = $mailer;
$this->userManager = $userManager;
$this->l10n = $l10nFactory->get('core');
diff --git a/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php b/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php
index 81feab32746..5781c1edf16 100644
--- a/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php
+++ b/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -45,7 +27,7 @@ class RemoteWipeNotificationsListener implements IEventListener {
private $timeFactory;
public function __construct(INotificationManager $notificationManager,
- ITimeFactory $timeFactory) {
+ ITimeFactory $timeFactory) {
$this->notificationManager = $notificationManager;
$this->timeFactory = $timeFactory;
}
@@ -63,7 +45,7 @@ class RemoteWipeNotificationsListener implements IEventListener {
$notification->setApp('auth')
->setUser($token->getUID())
->setDateTime($this->timeFactory->getDateTime())
- ->setObject('token', (string) $token->getId())
+ ->setObject('token', (string)$token->getId())
->setSubject($event, [
'name' => $token->getName(),
]);
diff --git a/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php
index 5e657be0763..a619021d192 100644
--- a/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedFilesCleanupListener.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -33,29 +16,34 @@ use OCP\Files\Config\IMountProviderCollection;
use OCP\Files\Storage\IStorage;
use OCP\User\Events\BeforeUserDeletedEvent;
use OCP\User\Events\UserDeletedEvent;
+use Psr\Log\LoggerInterface;
+/** @template-implements IEventListener<BeforeUserDeletedEvent|UserDeletedEvent> */
class UserDeletedFilesCleanupListener implements IEventListener {
/** @var array<string,IStorage> */
private $homeStorageCache = [];
- /** @var IMountProviderCollection */
- private $mountProviderCollection;
-
- public function __construct(IMountProviderCollection $mountProviderCollection) {
- $this->mountProviderCollection = $mountProviderCollection;
+ public function __construct(
+ private IMountProviderCollection $mountProviderCollection,
+ private LoggerInterface $logger,
+ ) {
}
public function handle(Event $event): void {
+ $user = $event->getUser();
+
// since we can't reliably get the user home storage after the user is deleted
// but the user deletion might get canceled during the before event
// we only cache the user home storage during the before event and then do the
// action deletion during the after event
if ($event instanceof BeforeUserDeletedEvent) {
- $userHome = $this->mountProviderCollection->getHomeMountForUser($event->getUser());
+ $this->logger->debug('Prepare deleting storage for user {userId}', ['userId' => $user->getUID()]);
+
+ $userHome = $this->mountProviderCollection->getHomeMountForUser($user);
$storage = $userHome->getStorage();
if (!$storage) {
- throw new \Exception("User has no home storage");
+ throw new \Exception('Account has no home storage');
}
// remove all wrappers, so we do the delete directly on the home storage bypassing any wrapper
@@ -67,16 +55,18 @@ class UserDeletedFilesCleanupListener implements IEventListener {
$this->homeStorageCache[$event->getUser()->getUID()] = $storage;
}
if ($event instanceof UserDeletedEvent) {
- if (!isset($this->homeStorageCache[$event->getUser()->getUID()])) {
- throw new \Exception("UserDeletedEvent fired without matching BeforeUserDeletedEvent");
+ if (!isset($this->homeStorageCache[$user->getUID()])) {
+ throw new \Exception('UserDeletedEvent fired without matching BeforeUserDeletedEvent');
}
- $storage = $this->homeStorageCache[$event->getUser()->getUID()];
+ $storage = $this->homeStorageCache[$user->getUID()];
$cache = $storage->getCache();
$storage->rmdir('');
+ $this->logger->debug('Deleted storage for user {userId}', ['userId' => $user->getUID()]);
+
if ($cache instanceof Cache) {
$cache->clear();
} else {
- throw new \Exception("Home storage has invalid cache");
+ throw new \Exception('Home storage has invalid cache');
}
}
}
diff --git a/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php
index e478c21239f..5f21c640780 100644
--- a/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
diff --git a/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php
index a09a08568d5..3631c04432c 100644
--- a/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -44,7 +26,7 @@ class UserDeletedTokenCleanupListener implements IEventListener {
private $logger;
public function __construct(Manager $manager,
- LoggerInterface $logger) {
+ LoggerInterface $logger) {
$this->manager = $manager;
$this->logger = $logger;
}
diff --git a/lib/private/Authentication/Listeners/UserDeletedWebAuthnCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedWebAuthnCleanupListener.php
index 4927c3ac7f9..67f8ff7cfcd 100644
--- a/lib/private/Authentication/Listeners/UserDeletedWebAuthnCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedWebAuthnCleanupListener.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Morris Jobke <hey@morrisjobke.de>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
@@ -31,6 +14,7 @@ use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\User\Events\UserDeletedEvent;
+/** @template-implements IEventListener<UserDeletedEvent> */
class UserDeletedWebAuthnCleanupListener implements IEventListener {
/** @var PublicKeyCredentialMapper */
private $credentialMapper;
diff --git a/lib/private/Authentication/Listeners/UserLoggedInListener.php b/lib/private/Authentication/Listeners/UserLoggedInListener.php
index df030c44749..a8d4baeafa1 100644
--- a/lib/private/Authentication/Listeners/UserLoggedInListener.php
+++ b/lib/private/Authentication/Listeners/UserLoggedInListener.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Listeners;
diff --git a/lib/private/Authentication/Login/ALoginCommand.php b/lib/private/Authentication/Login/ALoginCommand.php
index 7944eac1b62..a9f51f0da9e 100644
--- a/lib/private/Authentication/Login/ALoginCommand.php
+++ b/lib/private/Authentication/Login/ALoginCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/Chain.php b/lib/private/Authentication/Login/Chain.php
index 3c3179472c4..fc90d9225a7 100644
--- a/lib/private/Authentication/Login/Chain.php
+++ b/lib/private/Authentication/Login/Chain.php
@@ -3,90 +3,26 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
class Chain {
- /** @var PreLoginHookCommand */
- private $preLoginHookCommand;
-
- /** @var UserDisabledCheckCommand */
- private $userDisabledCheckCommand;
-
- /** @var UidLoginCommand */
- private $uidLoginCommand;
-
- /** @var EmailLoginCommand */
- private $emailLoginCommand;
-
- /** @var LoggedInCheckCommand */
- private $loggedInCheckCommand;
-
- /** @var CompleteLoginCommand */
- private $completeLoginCommand;
-
- /** @var CreateSessionTokenCommand */
- private $createSessionTokenCommand;
-
- /** @var ClearLostPasswordTokensCommand */
- private $clearLostPasswordTokensCommand;
-
- /** @var UpdateLastPasswordConfirmCommand */
- private $updateLastPasswordConfirmCommand;
-
- /** @var SetUserTimezoneCommand */
- private $setUserTimezoneCommand;
-
- /** @var TwoFactorCommand */
- private $twoFactorCommand;
-
- /** @var FinishRememberedLoginCommand */
- private $finishRememberedLoginCommand;
-
- public function __construct(PreLoginHookCommand $preLoginHookCommand,
- UserDisabledCheckCommand $userDisabledCheckCommand,
- UidLoginCommand $uidLoginCommand,
- EmailLoginCommand $emailLoginCommand,
- LoggedInCheckCommand $loggedInCheckCommand,
- CompleteLoginCommand $completeLoginCommand,
- CreateSessionTokenCommand $createSessionTokenCommand,
- ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand,
- UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand,
- SetUserTimezoneCommand $setUserTimezoneCommand,
- TwoFactorCommand $twoFactorCommand,
- FinishRememberedLoginCommand $finishRememberedLoginCommand
+ public function __construct(
+ private PreLoginHookCommand $preLoginHookCommand,
+ private UserDisabledCheckCommand $userDisabledCheckCommand,
+ private UidLoginCommand $uidLoginCommand,
+ private LoggedInCheckCommand $loggedInCheckCommand,
+ private CompleteLoginCommand $completeLoginCommand,
+ private CreateSessionTokenCommand $createSessionTokenCommand,
+ private ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand,
+ private UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand,
+ private SetUserTimezoneCommand $setUserTimezoneCommand,
+ private TwoFactorCommand $twoFactorCommand,
+ private FinishRememberedLoginCommand $finishRememberedLoginCommand,
+ private FlowV2EphemeralSessionsCommand $flowV2EphemeralSessionsCommand,
) {
- $this->preLoginHookCommand = $preLoginHookCommand;
- $this->userDisabledCheckCommand = $userDisabledCheckCommand;
- $this->uidLoginCommand = $uidLoginCommand;
- $this->emailLoginCommand = $emailLoginCommand;
- $this->loggedInCheckCommand = $loggedInCheckCommand;
- $this->completeLoginCommand = $completeLoginCommand;
- $this->createSessionTokenCommand = $createSessionTokenCommand;
- $this->clearLostPasswordTokensCommand = $clearLostPasswordTokensCommand;
- $this->updateLastPasswordConfirmCommand = $updateLastPasswordConfirmCommand;
- $this->setUserTimezoneCommand = $setUserTimezoneCommand;
- $this->twoFactorCommand = $twoFactorCommand;
- $this->finishRememberedLoginCommand = $finishRememberedLoginCommand;
}
public function process(LoginData $loginData): LoginResult {
@@ -94,9 +30,9 @@ class Chain {
$chain
->setNext($this->userDisabledCheckCommand)
->setNext($this->uidLoginCommand)
- ->setNext($this->emailLoginCommand)
->setNext($this->loggedInCheckCommand)
->setNext($this->completeLoginCommand)
+ ->setNext($this->flowV2EphemeralSessionsCommand)
->setNext($this->createSessionTokenCommand)
->setNext($this->clearLostPasswordTokensCommand)
->setNext($this->updateLastPasswordConfirmCommand)
diff --git a/lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php b/lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php
index 1643b5af1d5..40369c383ac 100644
--- a/lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php
+++ b/lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/CompleteLoginCommand.php b/lib/private/Authentication/Login/CompleteLoginCommand.php
index 46f7f1a3fa7..ec6fdf75f40 100644
--- a/lib/private/Authentication/Login/CompleteLoginCommand.php
+++ b/lib/private/Authentication/Login/CompleteLoginCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/CreateSessionTokenCommand.php b/lib/private/Authentication/Login/CreateSessionTokenCommand.php
index ba237dfbf20..7619ad90d93 100644
--- a/lib/private/Authentication/Login/CreateSessionTokenCommand.php
+++ b/lib/private/Authentication/Login/CreateSessionTokenCommand.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -39,7 +20,7 @@ class CreateSessionTokenCommand extends ALoginCommand {
private $userSession;
public function __construct(IConfig $config,
- Session $userSession) {
+ Session $userSession) {
$this->config = $config;
$this->userSession = $userSession;
}
diff --git a/lib/private/Authentication/Login/EmailLoginCommand.php b/lib/private/Authentication/Login/EmailLoginCommand.php
deleted file mode 100644
index 315fe450697..00000000000
--- a/lib/private/Authentication/Login/EmailLoginCommand.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-namespace OC\Authentication\Login;
-
-use OCP\IUserManager;
-
-class EmailLoginCommand extends ALoginCommand {
- /** @var IUserManager */
- private $userManager;
-
- public function __construct(IUserManager $userManager) {
- $this->userManager = $userManager;
- }
-
- public function process(LoginData $loginData): LoginResult {
- if ($loginData->getUser() === false) {
- if (!filter_var($loginData->getUsername(), FILTER_VALIDATE_EMAIL)) {
- return $this->processNextOrFinishSuccessfully($loginData);
- }
-
- $users = $this->userManager->getByEmail($loginData->getUsername());
- // we only allow login by email if unique
- if (count($users) === 1) {
- // FIXME: This is a workaround to still stick to configured LDAP login filters
- // this can be removed once the email login is properly implemented in the local user backend
- // as described in https://github.com/nextcloud/server/issues/5221
- if ($users[0]->getBackendClassName() === 'LDAP') {
- return $this->processNextOrFinishSuccessfully($loginData);
- }
-
- $username = $users[0]->getUID();
- if ($username !== $loginData->getUsername()) {
- $user = $this->userManager->checkPassword(
- $username,
- $loginData->getPassword()
- );
- if ($user !== false) {
- $loginData->setUser($user);
- $loginData->setUsername($username);
- }
- }
- }
- }
-
- return $this->processNextOrFinishSuccessfully($loginData);
- }
-}
diff --git a/lib/private/Authentication/Login/FinishRememberedLoginCommand.php b/lib/private/Authentication/Login/FinishRememberedLoginCommand.php
index 04ed7ed846e..3eb1f8f1a65 100644
--- a/lib/private/Authentication/Login/FinishRememberedLoginCommand.php
+++ b/lib/private/Authentication/Login/FinishRememberedLoginCommand.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -41,7 +23,7 @@ class FinishRememberedLoginCommand extends ALoginCommand {
}
public function process(LoginData $loginData): LoginResult {
- if ($loginData->isRememberLogin() && $this->config->getSystemValue('auto_logout', false) === false) {
+ if ($loginData->isRememberLogin() && !$this->config->getSystemValueBool('auto_logout', false)) {
$this->userSession->createRememberMeToken($loginData->getUser());
}
diff --git a/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php b/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php
new file mode 100644
index 00000000000..82dd829334d
--- /dev/null
+++ b/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php
@@ -0,0 +1,30 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Authentication\Login;
+
+use OC\Core\Controller\ClientFlowLoginV2Controller;
+use OCP\ISession;
+use OCP\IURLGenerator;
+
+class FlowV2EphemeralSessionsCommand extends ALoginCommand {
+ public function __construct(
+ private ISession $session,
+ private IURLGenerator $urlGenerator,
+ ) {
+ }
+
+ public function process(LoginData $loginData): LoginResult {
+ $loginV2GrantRoute = $this->urlGenerator->linkToRoute('core.ClientFlowLoginV2.grantPage');
+ if (str_starts_with($loginData->getRedirectUrl() ?? '', $loginV2GrantRoute)) {
+ $this->session->set(ClientFlowLoginV2Controller::EPHEMERAL_NAME, true);
+ }
+
+ return $this->processNextOrFinishSuccessfully($loginData);
+ }
+}
diff --git a/lib/private/Authentication/Login/LoggedInCheckCommand.php b/lib/private/Authentication/Login/LoggedInCheckCommand.php
index dc1a4d2d883..b6b59ced6ce 100644
--- a/lib/private/Authentication/Login/LoggedInCheckCommand.php
+++ b/lib/private/Authentication/Login/LoggedInCheckCommand.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -39,7 +20,7 @@ class LoggedInCheckCommand extends ALoginCommand {
private $dispatcher;
public function __construct(LoggerInterface $logger,
- IEventDispatcher $dispatcher) {
+ IEventDispatcher $dispatcher) {
$this->logger = $logger;
$this->dispatcher = $dispatcher;
}
diff --git a/lib/private/Authentication/Login/LoginData.php b/lib/private/Authentication/Login/LoginData.php
index 240a1dc6476..1ad97a9d559 100644
--- a/lib/private/Authentication/Login/LoginData.php
+++ b/lib/private/Authentication/Login/LoginData.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -55,11 +37,11 @@ class LoginData {
private $rememberLogin = true;
public function __construct(IRequest $request,
- string $username,
- ?string $password,
- string $redirectUrl = null,
- string $timeZone = '',
- string $timeZoneOffset = '') {
+ string $username,
+ ?string $password,
+ ?string $redirectUrl = null,
+ string $timeZone = '',
+ string $timeZoneOffset = '') {
$this->request = $request;
$this->username = $username;
$this->password = $password;
diff --git a/lib/private/Authentication/Login/LoginResult.php b/lib/private/Authentication/Login/LoginResult.php
index dec012c2fc9..95e87b520e3 100644
--- a/lib/private/Authentication/Login/LoginResult.php
+++ b/lib/private/Authentication/Login/LoginResult.php
@@ -3,28 +3,13 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
+use OC\Core\Controller\LoginController;
+
class LoginResult {
/** @var bool */
private $success;
@@ -59,7 +44,10 @@ class LoginResult {
return $result;
}
- public static function failure(LoginData $data, string $msg = null): LoginResult {
+ /**
+ * @param LoginController::LOGIN_MSG_*|null $msg
+ */
+ public static function failure(LoginData $data, ?string $msg = null): LoginResult {
$result = new static(false, $data);
if ($msg !== null) {
$result->setErrorMessage($msg);
diff --git a/lib/private/Authentication/Login/PreLoginHookCommand.php b/lib/private/Authentication/Login/PreLoginHookCommand.php
index 21c97433f5a..d5aa174094d 100644
--- a/lib/private/Authentication/Login/PreLoginHookCommand.php
+++ b/lib/private/Authentication/Login/PreLoginHookCommand.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/SetUserTimezoneCommand.php b/lib/private/Authentication/Login/SetUserTimezoneCommand.php
index f68fce1771e..90bc444ae7d 100644
--- a/lib/private/Authentication/Login/SetUserTimezoneCommand.php
+++ b/lib/private/Authentication/Login/SetUserTimezoneCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -36,7 +19,7 @@ class SetUserTimezoneCommand extends ALoginCommand {
private $session;
public function __construct(IConfig $config,
- ISession $session) {
+ ISession $session) {
$this->config = $config;
$this->session = $session;
}
diff --git a/lib/private/Authentication/Login/TwoFactorCommand.php b/lib/private/Authentication/Login/TwoFactorCommand.php
index 256d88ffa81..fc5285221a2 100644
--- a/lib/private/Authentication/Login/TwoFactorCommand.php
+++ b/lib/private/Authentication/Login/TwoFactorCommand.php
@@ -3,35 +3,17 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
-use function array_pop;
-use function count;
use OC\Authentication\TwoFactorAuth\Manager;
use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\IURLGenerator;
+use function array_pop;
+use function count;
class TwoFactorCommand extends ALoginCommand {
/** @var Manager */
@@ -44,8 +26,8 @@ class TwoFactorCommand extends ALoginCommand {
private $urlGenerator;
public function __construct(Manager $twoFactorManager,
- MandatoryTwoFactor $mandatoryTwoFactor,
- IURLGenerator $urlGenerator) {
+ MandatoryTwoFactor $mandatoryTwoFactor,
+ IURLGenerator $urlGenerator) {
$this->twoFactorManager = $twoFactorManager;
$this->mandatoryTwoFactor = $mandatoryTwoFactor;
$this->urlGenerator = $urlGenerator;
diff --git a/lib/private/Authentication/Login/UidLoginCommand.php b/lib/private/Authentication/Login/UidLoginCommand.php
index d3216b6aad8..511b5f61e0e 100644
--- a/lib/private/Authentication/Login/UidLoginCommand.php
+++ b/lib/private/Authentication/Login/UidLoginCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/UpdateLastPasswordConfirmCommand.php b/lib/private/Authentication/Login/UpdateLastPasswordConfirmCommand.php
index 571ea931d8a..0582239e9de 100644
--- a/lib/private/Authentication/Login/UpdateLastPasswordConfirmCommand.php
+++ b/lib/private/Authentication/Login/UpdateLastPasswordConfirmCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/Login/UserDisabledCheckCommand.php b/lib/private/Authentication/Login/UserDisabledCheckCommand.php
index 7cf4c7235ec..8777aa6dcea 100644
--- a/lib/private/Authentication/Login/UserDisabledCheckCommand.php
+++ b/lib/private/Authentication/Login/UserDisabledCheckCommand.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -38,7 +20,7 @@ class UserDisabledCheckCommand extends ALoginCommand {
private $logger;
public function __construct(IUserManager $userManager,
- LoggerInterface $logger) {
+ LoggerInterface $logger) {
$this->userManager = $userManager;
$this->logger = $logger;
}
diff --git a/lib/private/Authentication/Login/WebAuthnChain.php b/lib/private/Authentication/Login/WebAuthnChain.php
index f3ebc313a44..ae523c43da6 100644
--- a/lib/private/Authentication/Login/WebAuthnChain.php
+++ b/lib/private/Authentication/Login/WebAuthnChain.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
@@ -57,15 +40,15 @@ class WebAuthnChain {
private $webAuthnLoginCommand;
public function __construct(UserDisabledCheckCommand $userDisabledCheckCommand,
- WebAuthnLoginCommand $webAuthnLoginCommand,
- LoggedInCheckCommand $loggedInCheckCommand,
- CompleteLoginCommand $completeLoginCommand,
- CreateSessionTokenCommand $createSessionTokenCommand,
- ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand,
- UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand,
- SetUserTimezoneCommand $setUserTimezoneCommand,
- TwoFactorCommand $twoFactorCommand,
- FinishRememberedLoginCommand $finishRememberedLoginCommand
+ WebAuthnLoginCommand $webAuthnLoginCommand,
+ LoggedInCheckCommand $loggedInCheckCommand,
+ CompleteLoginCommand $completeLoginCommand,
+ CreateSessionTokenCommand $createSessionTokenCommand,
+ ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand,
+ UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand,
+ SetUserTimezoneCommand $setUserTimezoneCommand,
+ TwoFactorCommand $twoFactorCommand,
+ FinishRememberedLoginCommand $finishRememberedLoginCommand,
) {
$this->userDisabledCheckCommand = $userDisabledCheckCommand;
$this->webAuthnLoginCommand = $webAuthnLoginCommand;
diff --git a/lib/private/Authentication/Login/WebAuthnLoginCommand.php b/lib/private/Authentication/Login/WebAuthnLoginCommand.php
index 478a579853c..8f14e5b3f6d 100644
--- a/lib/private/Authentication/Login/WebAuthnLoginCommand.php
+++ b/lib/private/Authentication/Login/WebAuthnLoginCommand.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Login;
diff --git a/lib/private/Authentication/LoginCredentials/Credentials.php b/lib/private/Authentication/LoginCredentials/Credentials.php
index 69bfc2ba198..3414034b33c 100644
--- a/lib/private/Authentication/LoginCredentials/Credentials.php
+++ b/lib/private/Authentication/LoginCredentials/Credentials.php
@@ -1,24 +1,8 @@
<?php
+
/**
- * @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\LoginCredentials;
diff --git a/lib/private/Authentication/LoginCredentials/Store.php b/lib/private/Authentication/LoginCredentials/Store.php
index 3a09e983ee8..67c5712715c 100644
--- a/lib/private/Authentication/LoginCredentials/Store.php
+++ b/lib/private/Authentication/LoginCredentials/Store.php
@@ -3,36 +3,20 @@
declare(strict_types=1);
/**
- * @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\LoginCredentials;
-use OC\Authentication\Exceptions\InvalidTokenException;
+use Exception;
use OC\Authentication\Exceptions\PasswordlessTokenException;
use OC\Authentication\Token\IProvider;
use OCP\Authentication\Exceptions\CredentialsUnavailableException;
+use OCP\Authentication\Exceptions\InvalidTokenException;
use OCP\Authentication\LoginCredentials\ICredentials;
use OCP\Authentication\LoginCredentials\IStore;
use OCP\ISession;
+use OCP\Security\ICrypto;
use OCP\Session\Exceptions\SessionNotAvailableException;
use OCP\Util;
use Psr\Log\LoggerInterface;
@@ -47,9 +31,12 @@ class Store implements IStore {
/** @var IProvider|null */
private $tokenProvider;
- public function __construct(ISession $session,
- LoggerInterface $logger,
- IProvider $tokenProvider = null) {
+ public function __construct(
+ ISession $session,
+ LoggerInterface $logger,
+ private readonly ICrypto $crypto,
+ ?IProvider $tokenProvider = null,
+ ) {
$this->session = $session;
$this->logger = $logger;
$this->tokenProvider = $tokenProvider;
@@ -63,6 +50,9 @@ class Store implements IStore {
* @param array $params
*/
public function authenticate(array $params) {
+ if ($params['password'] !== null) {
+ $params['password'] = $this->crypto->encrypt((string)$params['password']);
+ }
$this->session->set('login_credentials', json_encode($params));
}
@@ -109,6 +99,13 @@ class Store implements IStore {
if ($trySession && $this->session->exists('login_credentials')) {
/** @var array $creds */
$creds = json_decode($this->session->get('login_credentials'), true);
+ if ($creds['password'] !== null) {
+ try {
+ $creds['password'] = $this->crypto->decrypt($creds['password']);
+ } catch (Exception $e) {
+ //decryption failed, continue with old password as it is
+ }
+ }
return new Credentials(
$creds['uid'],
$creds['loginName'] ?? $this->session->get('loginname') ?? $creds['uid'], // Pre 20 didn't have a loginName property, hence fall back to the session value and then to the UID
diff --git a/lib/private/Authentication/Notifications/Notifier.php b/lib/private/Authentication/Notifications/Notifier.php
index 8cf5d653771..a81e385d8b1 100644
--- a/lib/private/Authentication/Notifications/Notifier.php
+++ b/lib/private/Authentication/Notifications/Notifier.php
@@ -3,33 +3,15 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Notifications;
-use InvalidArgumentException;
use OCP\L10N\IFactory as IL10nFactory;
use OCP\Notification\INotification;
use OCP\Notification\INotifier;
+use OCP\Notification\UnknownNotificationException;
class Notifier implements INotifier {
/** @var IL10nFactory */
@@ -45,7 +27,7 @@ class Notifier implements INotifier {
public function prepare(INotification $notification, string $languageCode): INotification {
if ($notification->getApp() !== 'auth') {
// Not my app => throw
- throw new InvalidArgumentException();
+ throw new UnknownNotificationException();
}
// Read the language from the notification
@@ -70,7 +52,7 @@ class Notifier implements INotifier {
return $notification;
default:
// Unknown subject => Unknown notification => throw
- throw new InvalidArgumentException();
+ throw new UnknownNotificationException();
}
}
diff --git a/lib/private/Authentication/Token/INamedToken.php b/lib/private/Authentication/Token/INamedToken.php
index 96a7719fb41..9a90cfc7d76 100644
--- a/lib/private/Authentication/Token/INamedToken.php
+++ b/lib/private/Authentication/Token/INamedToken.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Daniel Kesselberg (mail@danielkesselberg.de)
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php
index b5af3f3a5ee..d47427e79bf 100644
--- a/lib/private/Authentication/Token/IProvider.php
+++ b/lib/private/Authentication/Token/IProvider.php
@@ -3,36 +3,17 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Marcel Waldvogel <marcel.waldvogel@uni-konstanz.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Token;
-use OC\Authentication\Exceptions\ExpiredTokenException;
-use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
-use OC\Authentication\Exceptions\WipeTokenException;
+use OCP\Authentication\Exceptions\ExpiredTokenException;
+use OCP\Authentication\Exceptions\InvalidTokenException;
+use OCP\Authentication\Exceptions\WipeTokenException;
+use OCP\Authentication\Token\IToken as OCPIToken;
interface IProvider {
/**
@@ -45,16 +26,18 @@ interface IProvider {
* @param string $name Name will be trimmed to 120 chars when longer
* @param int $type token type
* @param int $remember whether the session token should be used for remember-me
- * @return IToken
+ * @return OCPIToken
* @throws \RuntimeException when OpenSSL reports a problem
*/
public function generateToken(string $token,
- string $uid,
- string $loginName,
- ?string $password,
- string $name,
- int $type = IToken::TEMPORARY_TOKEN,
- int $remember = IToken::DO_NOT_REMEMBER): IToken;
+ string $uid,
+ string $loginName,
+ ?string $password,
+ string $name,
+ int $type = OCPIToken::TEMPORARY_TOKEN,
+ int $remember = OCPIToken::DO_NOT_REMEMBER,
+ ?array $scope = null,
+ ): OCPIToken;
/**
* Get a token by token id
@@ -63,9 +46,9 @@ interface IProvider {
* @throws InvalidTokenException
* @throws ExpiredTokenException
* @throws WipeTokenException
- * @return IToken
+ * @return OCPIToken
*/
- public function getToken(string $tokenId): IToken;
+ public function getToken(string $tokenId): OCPIToken;
/**
* Get a token by token id
@@ -74,9 +57,9 @@ interface IProvider {
* @throws InvalidTokenException
* @throws ExpiredTokenException
* @throws WipeTokenException
- * @return IToken
+ * @return OCPIToken
*/
- public function getTokenById(int $tokenId): IToken;
+ public function getTokenById(int $tokenId): OCPIToken;
/**
* Duplicate an existing session token
@@ -85,9 +68,9 @@ interface IProvider {
* @param string $sessionId
* @throws InvalidTokenException
* @throws \RuntimeException when OpenSSL reports a problem
- * @return IToken The new token
+ * @return OCPIToken The new token
*/
- public function renewSessionToken(string $oldSessionId, string $sessionId): IToken;
+ public function renewSessionToken(string $oldSessionId, string $sessionId): OCPIToken;
/**
* Invalidate (delete) the given session token
@@ -110,18 +93,23 @@ interface IProvider {
public function invalidateOldTokens();
/**
+ * Invalidate (delete) tokens last used before a given date
+ */
+ public function invalidateLastUsedBefore(string $uid, int $before): void;
+
+ /**
* Save the updated token
*
- * @param IToken $token
+ * @param OCPIToken $token
*/
- public function updateToken(IToken $token);
+ public function updateToken(OCPIToken $token);
/**
* Update token activity timestamp
*
- * @param IToken $token
+ * @param OCPIToken $token
*/
- public function updateTokenActivity(IToken $token);
+ public function updateTokenActivity(OCPIToken $token);
/**
* Get all tokens of a user
@@ -130,49 +118,49 @@ interface IProvider {
* where a high number of (session) tokens is generated
*
* @param string $uid
- * @return IToken[]
+ * @return OCPIToken[]
*/
public function getTokenByUser(string $uid): array;
/**
* Get the (unencrypted) password of the given token
*
- * @param IToken $savedToken
+ * @param OCPIToken $savedToken
* @param string $tokenId
* @throws InvalidTokenException
* @throws PasswordlessTokenException
* @return string
*/
- public function getPassword(IToken $savedToken, string $tokenId): string;
+ public function getPassword(OCPIToken $savedToken, string $tokenId): string;
/**
* Encrypt and set the password of the given token
*
- * @param IToken $token
+ * @param OCPIToken $token
* @param string $tokenId
* @param string $password
* @throws InvalidTokenException
*/
- public function setPassword(IToken $token, string $tokenId, string $password);
+ public function setPassword(OCPIToken $token, string $tokenId, string $password);
/**
* Rotate the token. Useful for for example oauth tokens
*
- * @param IToken $token
+ * @param OCPIToken $token
* @param string $oldTokenId
* @param string $newTokenId
- * @return IToken
+ * @return OCPIToken
* @throws \RuntimeException when OpenSSL reports a problem
*/
- public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken;
+ public function rotate(OCPIToken $token, string $oldTokenId, string $newTokenId): OCPIToken;
/**
* Marks a token as having an invalid password.
*
- * @param IToken $token
+ * @param OCPIToken $token
* @param string $tokenId
*/
- public function markPasswordInvalid(IToken $token, string $tokenId);
+ public function markPasswordInvalid(OCPIToken $token, string $tokenId);
/**
* Update all the passwords of $uid if required
diff --git a/lib/private/Authentication/Token/IToken.php b/lib/private/Authentication/Token/IToken.php
index 5ca4eaea843..2028a0b328c 100644
--- a/lib/private/Authentication/Token/IToken.php
+++ b/lib/private/Authentication/Token/IToken.php
@@ -1,134 +1,17 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Token;
-use JsonSerializable;
-
-interface IToken extends JsonSerializable {
- public const TEMPORARY_TOKEN = 0;
- public const PERMANENT_TOKEN = 1;
- public const WIPE_TOKEN = 2;
- public const DO_NOT_REMEMBER = 0;
- public const REMEMBER = 1;
-
- /**
- * Get the token ID
- *
- * @return int
- */
- public function getId(): int;
-
- /**
- * Get the user UID
- *
- * @return string
- */
- public function getUID(): string;
-
- /**
- * Get the login name used when generating the token
- *
- * @return string
- */
- public function getLoginName(): string;
-
- /**
- * Get the (encrypted) login password
- *
- * @return string|null
- */
- public function getPassword();
-
- /**
- * Get the timestamp of the last password check
- *
- * @return int
- */
- public function getLastCheck(): int;
-
- /**
- * Set the timestamp of the last password check
- *
- * @param int $time
- */
- public function setLastCheck(int $time);
-
- /**
- * Get the authentication scope for this token
- *
- * @return string
- */
- public function getScope(): string;
+use OCP\Authentication\Token\IToken as OCPIToken;
- /**
- * Get the authentication scope for this token
- *
- * @return array
- */
- public function getScopeAsArray(): array;
-
- /**
- * Set the authentication scope for this token
- *
- * @param array $scope
- */
- public function setScope($scope);
-
- /**
- * Get the name of the token
- * @return string
- */
- public function getName(): string;
-
- /**
- * Get the remember state of the token
- *
- * @return int
- */
- public function getRemember(): int;
-
- /**
- * Set the token
- *
- * @param string $token
- */
- public function setToken(string $token);
-
- /**
- * Set the password
- *
- * @param string $password
- */
- public function setPassword(string $password);
-
- /**
- * Set the expiration time of the token
- *
- * @param int|null $expires
- */
- public function setExpires($expires);
+/**
+ * @deprecated 28.0.0 use {@see \OCP\Authentication\Token\IToken} instead
+ */
+interface IToken extends OCPIToken {
}
diff --git a/lib/private/Authentication/Token/IWipeableToken.php b/lib/private/Authentication/Token/IWipeableToken.php
index 5ba994e0d5e..fc1476785cd 100644
--- a/lib/private/Authentication/Token/IWipeableToken.php
+++ b/lib/private/Authentication/Token/IWipeableToken.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
diff --git a/lib/private/Authentication/Token/Manager.php b/lib/private/Authentication/Token/Manager.php
index 59c7ca714c6..6953f47b004 100644
--- a/lib/private/Authentication/Token/Manager.php
+++ b/lib/private/Authentication/Token/Manager.php
@@ -1,39 +1,22 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
-use OC\Authentication\Exceptions\ExpiredTokenException;
-use OC\Authentication\Exceptions\InvalidTokenException;
+use OC\Authentication\Exceptions\InvalidTokenException as OcInvalidTokenException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
-use OC\Authentication\Exceptions\WipeTokenException;
+use OCP\Authentication\Exceptions\ExpiredTokenException;
+use OCP\Authentication\Exceptions\InvalidTokenException;
+use OCP\Authentication\Exceptions\WipeTokenException;
+use OCP\Authentication\Token\IProvider as OCPIProvider;
+use OCP\Authentication\Token\IToken as OCPIToken;
-class Manager implements IProvider {
+class Manager implements IProvider, OCPIProvider {
/** @var PublicKeyTokenProvider */
private $publicKeyTokenProvider;
@@ -51,15 +34,17 @@ class Manager implements IProvider {
* @param string $name Name will be trimmed to 120 chars when longer
* @param int $type token type
* @param int $remember whether the session token should be used for remember-me
- * @return IToken
+ * @return OCPIToken
*/
public function generateToken(string $token,
- string $uid,
- string $loginName,
- $password,
- string $name,
- int $type = IToken::TEMPORARY_TOKEN,
- int $remember = IToken::DO_NOT_REMEMBER): IToken {
+ string $uid,
+ string $loginName,
+ $password,
+ string $name,
+ int $type = OCPIToken::TEMPORARY_TOKEN,
+ int $remember = OCPIToken::DO_NOT_REMEMBER,
+ ?array $scope = null,
+ ): OCPIToken {
if (mb_strlen($name) > 128) {
$name = mb_substr($name, 0, 120) . '…';
}
@@ -72,7 +57,8 @@ class Manager implements IProvider {
$password,
$name,
$type,
- $remember
+ $remember,
+ $scope,
);
} catch (UniqueConstraintViolationException $e) {
// It's rare, but if two requests of the same session (e.g. env-based SAML)
@@ -92,10 +78,10 @@ class Manager implements IProvider {
/**
* Save the updated token
*
- * @param IToken $token
+ * @param OCPIToken $token
* @throws InvalidTokenException
*/
- public function updateToken(IToken $token) {
+ public function updateToken(OCPIToken $token) {
$provider = $this->getProvider($token);
$provider->updateToken($token);
}
@@ -104,16 +90,16 @@ class Manager implements IProvider {
* Update token activity timestamp
*
* @throws InvalidTokenException
- * @param IToken $token
+ * @param OCPIToken $token
*/
- public function updateTokenActivity(IToken $token) {
+ public function updateTokenActivity(OCPIToken $token) {
$provider = $this->getProvider($token);
$provider->updateTokenActivity($token);
}
/**
* @param string $uid
- * @return IToken[]
+ * @return OCPIToken[]
*/
public function getTokenByUser(string $uid): array {
return $this->publicKeyTokenProvider->getTokenByUser($uid);
@@ -125,9 +111,9 @@ class Manager implements IProvider {
* @param string $tokenId
* @throws InvalidTokenException
* @throws \RuntimeException when OpenSSL reports a problem
- * @return IToken
+ * @return OCPIToken
*/
- public function getToken(string $tokenId): IToken {
+ public function getToken(string $tokenId): OCPIToken {
try {
return $this->publicKeyTokenProvider->getToken($tokenId);
} catch (WipeTokenException $e) {
@@ -144,9 +130,9 @@ class Manager implements IProvider {
*
* @param int $tokenId
* @throws InvalidTokenException
- * @return IToken
+ * @return OCPIToken
*/
- public function getTokenById(int $tokenId): IToken {
+ public function getTokenById(int $tokenId): OCPIToken {
try {
return $this->publicKeyTokenProvider->getTokenById($tokenId);
} catch (ExpiredTokenException $e) {
@@ -162,9 +148,9 @@ class Manager implements IProvider {
* @param string $oldSessionId
* @param string $sessionId
* @throws InvalidTokenException
- * @return IToken
+ * @return OCPIToken
*/
- public function renewSessionToken(string $oldSessionId, string $sessionId): IToken {
+ public function renewSessionToken(string $oldSessionId, string $sessionId): OCPIToken {
try {
return $this->publicKeyTokenProvider->renewSessionToken($oldSessionId, $sessionId);
} catch (ExpiredTokenException $e) {
@@ -175,18 +161,18 @@ class Manager implements IProvider {
}
/**
- * @param IToken $savedToken
+ * @param OCPIToken $savedToken
* @param string $tokenId session token
* @throws InvalidTokenException
* @throws PasswordlessTokenException
* @return string
*/
- public function getPassword(IToken $savedToken, string $tokenId): string {
+ public function getPassword(OCPIToken $savedToken, string $tokenId): string {
$provider = $this->getProvider($savedToken);
return $provider->getPassword($savedToken, $tokenId);
}
- public function setPassword(IToken $token, string $tokenId, string $password) {
+ public function setPassword(OCPIToken $token, string $tokenId, string $password) {
$provider = $this->getProvider($token);
$provider->setPassword($token, $tokenId, $password);
}
@@ -203,40 +189,55 @@ class Manager implements IProvider {
$this->publicKeyTokenProvider->invalidateOldTokens();
}
+ public function invalidateLastUsedBefore(string $uid, int $before): void {
+ $this->publicKeyTokenProvider->invalidateLastUsedBefore($uid, $before);
+ }
+
/**
- * @param IToken $token
+ * @param OCPIToken $token
* @param string $oldTokenId
* @param string $newTokenId
- * @return IToken
+ * @return OCPIToken
* @throws InvalidTokenException
* @throws \RuntimeException when OpenSSL reports a problem
*/
- public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
+ public function rotate(OCPIToken $token, string $oldTokenId, string $newTokenId): OCPIToken {
if ($token instanceof PublicKeyToken) {
return $this->publicKeyTokenProvider->rotate($token, $oldTokenId, $newTokenId);
}
- throw new InvalidTokenException();
+ /** @psalm-suppress DeprecatedClass We have to throw the OC version so both OC and OCP catches catch it */
+ throw new OcInvalidTokenException();
}
/**
- * @param IToken $token
+ * @param OCPIToken $token
* @return IProvider
* @throws InvalidTokenException
*/
- private function getProvider(IToken $token): IProvider {
+ private function getProvider(OCPIToken $token): IProvider {
if ($token instanceof PublicKeyToken) {
return $this->publicKeyTokenProvider;
}
- throw new InvalidTokenException();
+ /** @psalm-suppress DeprecatedClass We have to throw the OC version so both OC and OCP catches catch it */
+ throw new OcInvalidTokenException();
}
- public function markPasswordInvalid(IToken $token, string $tokenId) {
+ public function markPasswordInvalid(OCPIToken $token, string $tokenId) {
$this->getProvider($token)->markPasswordInvalid($token, $tokenId);
}
public function updatePasswords(string $uid, string $password) {
$this->publicKeyTokenProvider->updatePasswords($uid, $password);
}
+
+ public function invalidateTokensOfUser(string $uid, ?string $clientName) {
+ $tokens = $this->getTokenByUser($uid);
+ foreach ($tokens as $token) {
+ if ($clientName === null || ($token->getName() === $clientName)) {
+ $this->invalidateTokenById($uid, $token->getId());
+ }
+ }
+ }
}
diff --git a/lib/private/Authentication/Token/PublicKeyToken.php b/lib/private/Authentication/Token/PublicKeyToken.php
index 45335e17c31..be427ab4839 100644
--- a/lib/private/Authentication/Token/PublicKeyToken.php
+++ b/lib/private/Authentication/Token/PublicKeyToken.php
@@ -3,31 +3,14 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
use OCP\AppFramework\Db\Entity;
+use OCP\Authentication\Token\IToken;
+use OCP\DB\Types;
/**
* @method void setId(int $id)
@@ -106,16 +89,16 @@ class PublicKeyToken extends Entity implements INamedToken, IWipeableToken {
$this->addType('passwordHash', 'string');
$this->addType('name', 'string');
$this->addType('token', 'string');
- $this->addType('type', 'int');
- $this->addType('remember', 'int');
- $this->addType('lastActivity', 'int');
- $this->addType('lastCheck', 'int');
+ $this->addType('type', Types::INTEGER);
+ $this->addType('remember', Types::INTEGER);
+ $this->addType('lastActivity', Types::INTEGER);
+ $this->addType('lastCheck', Types::INTEGER);
$this->addType('scope', 'string');
- $this->addType('expires', 'int');
+ $this->addType('expires', Types::INTEGER);
$this->addType('publicKey', 'string');
$this->addType('privateKey', 'string');
- $this->addType('version', 'int');
- $this->addType('passwordInvalid', 'bool');
+ $this->addType('version', Types::INTEGER);
+ $this->addType('passwordInvalid', Types::BOOLEAN);
}
public function getId(): int {
@@ -137,10 +120,8 @@ class PublicKeyToken extends Entity implements INamedToken, IWipeableToken {
/**
* Get the (encrypted) login password
- *
- * @return string|null
*/
- public function getPassword() {
+ public function getPassword(): ?string {
return parent::getPassword();
}
@@ -165,10 +146,8 @@ class PublicKeyToken extends Entity implements INamedToken, IWipeableToken {
/**
* Get the timestamp of the last password check
- *
- * @param int $time
*/
- public function setLastCheck(int $time) {
+ public function setLastCheck(int $time): void {
parent::setLastCheck($time);
}
@@ -185,13 +164,13 @@ class PublicKeyToken extends Entity implements INamedToken, IWipeableToken {
$scope = json_decode($this->getScope(), true);
if (!$scope) {
return [
- 'filesystem' => true
+ IToken::SCOPE_FILESYSTEM => true
];
}
return $scope;
}
- public function setScope($scope) {
+ public function setScope(array|string|null $scope): void {
if (is_array($scope)) {
parent::setScope(json_encode($scope));
} else {
@@ -211,15 +190,15 @@ class PublicKeyToken extends Entity implements INamedToken, IWipeableToken {
return parent::getRemember();
}
- public function setToken(string $token) {
+ public function setToken(string $token): void {
parent::setToken($token);
}
- public function setPassword(string $password = null) {
+ public function setPassword(?string $password = null): void {
parent::setPassword($password);
}
- public function setExpires($expires) {
+ public function setExpires($expires): void {
parent::setExpires($expires);
}
diff --git a/lib/private/Authentication/Token/PublicKeyTokenMapper.php b/lib/private/Authentication/Token/PublicKeyTokenMapper.php
index 7b11ef8adf3..9aabd69e57a 100644
--- a/lib/private/Authentication/Token/PublicKeyTokenMapper.php
+++ b/lib/private/Authentication/Token/PublicKeyTokenMapper.php
@@ -3,32 +3,14 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\QBMapper;
+use OCP\Authentication\Token\IToken;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
@@ -42,8 +24,6 @@ class PublicKeyTokenMapper extends QBMapper {
/**
* Invalidate (delete) a given token
- *
- * @param string $token
*/
public function invalidate(string $token) {
/* @var $qb IQueryBuilder */
@@ -51,22 +31,34 @@ class PublicKeyTokenMapper extends QBMapper {
$qb->delete($this->tableName)
->where($qb->expr()->eq('token', $qb->createNamedParameter($token)))
->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)))
- ->execute();
+ ->executeStatement();
}
/**
* @param int $olderThan
- * @param int $remember
+ * @param int $type
+ * @param int|null $remember
*/
- public function invalidateOld(int $olderThan, int $remember = IToken::DO_NOT_REMEMBER) {
+ public function invalidateOld(int $olderThan, int $type = IToken::TEMPORARY_TOKEN, ?int $remember = null) {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
- $qb->delete($this->tableName)
+ $delete = $qb->delete($this->tableName)
->where($qb->expr()->lt('last_activity', $qb->createNamedParameter($olderThan, IQueryBuilder::PARAM_INT)))
- ->andWhere($qb->expr()->eq('type', $qb->createNamedParameter(IToken::TEMPORARY_TOKEN, IQueryBuilder::PARAM_INT)))
- ->andWhere($qb->expr()->eq('remember', $qb->createNamedParameter($remember, IQueryBuilder::PARAM_INT)))
- ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)))
- ->execute();
+ ->andWhere($qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)));
+ if ($remember !== null) {
+ $delete->andWhere($qb->expr()->eq('remember', $qb->createNamedParameter($remember, IQueryBuilder::PARAM_INT)));
+ }
+ $delete->executeStatement();
+ }
+
+ public function invalidateLastUsedBefore(string $uid, int $before): int {
+ $qb = $this->db->getQueryBuilder();
+ $qb->delete($this->tableName)
+ ->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
+ ->andWhere($qb->expr()->lt('last_activity', $qb->createNamedParameter($before, IQueryBuilder::PARAM_INT)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)));
+ return $qb->executeStatement();
}
/**
@@ -81,7 +73,7 @@ class PublicKeyTokenMapper extends QBMapper {
->from($this->tableName)
->where($qb->expr()->eq('token', $qb->createNamedParameter($token)))
->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)))
- ->execute();
+ ->executeQuery();
$data = $result->fetch();
$result->closeCursor();
@@ -103,7 +95,7 @@ class PublicKeyTokenMapper extends QBMapper {
->from($this->tableName)
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)))
- ->execute();
+ ->executeQuery();
$data = $result->fetch();
$result->closeCursor();
@@ -130,7 +122,7 @@ class PublicKeyTokenMapper extends QBMapper {
->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)))
->setMaxResults(1000);
- $result = $qb->execute();
+ $result = $qb->executeQuery();
$data = $result->fetchAll();
$result->closeCursor();
@@ -141,14 +133,15 @@ class PublicKeyTokenMapper extends QBMapper {
return $entities;
}
- public function deleteById(string $uid, int $id) {
+ public function getTokenByUserAndId(string $uid, int $id): ?string {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
- $qb->delete($this->tableName)
+ $qb->select('token')
+ ->from($this->tableName)
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)));
- $qb->execute();
+ return $qb->executeQuery()->fetchOne() ?: null;
}
/**
@@ -161,7 +154,7 @@ class PublicKeyTokenMapper extends QBMapper {
$qb->delete($this->tableName)
->where($qb->expr()->eq('name', $qb->createNamedParameter($name), IQueryBuilder::PARAM_STR))
->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)));
- $qb->execute();
+ $qb->executeStatement();
}
public function deleteTempToken(PublicKeyToken $except) {
@@ -173,7 +166,7 @@ class PublicKeyTokenMapper extends QBMapper {
->andWhere($qb->expr()->neq('id', $qb->createNamedParameter($except->getId())))
->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)));
- $qb->execute();
+ $qb->executeStatement();
}
public function hasExpiredTokens(string $uid): bool {
@@ -184,7 +177,7 @@ class PublicKeyTokenMapper extends QBMapper {
->andWhere($qb->expr()->eq('password_invalid', $qb->createNamedParameter(true), IQueryBuilder::PARAM_BOOL))
->setMaxResults(1);
- $cursor = $qb->execute();
+ $cursor = $qb->executeQuery();
$data = $cursor->fetchAll();
$cursor->closeCursor();
@@ -229,4 +222,31 @@ class PublicKeyTokenMapper extends QBMapper {
);
$update->executeStatement();
}
+
+ public function updateHashesForUser(string $userId, string $passwordHash): void {
+ $qb = $this->db->getQueryBuilder();
+ $update = $qb->update($this->getTableName())
+ ->set('password_hash', $qb->createNamedParameter($passwordHash))
+ ->where(
+ $qb->expr()->eq('uid', $qb->createNamedParameter($userId))
+ );
+ $update->executeStatement();
+ }
+
+ public function getFirstTokenForUser(string $userId): ?PublicKeyToken {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('uid', $qb->createNamedParameter($userId)))
+ ->setMaxResults(1)
+ ->orderBy('id');
+ $result = $qb->executeQuery();
+
+ $data = $result->fetch();
+ $result->closeCursor();
+ if ($data === false) {
+ return null;
+ }
+ return PublicKeyToken::fromRow($data);
+ }
}
diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
index c8adec24b31..12c3a1d535b 100644
--- a/lib/private/Authentication/Token/PublicKeyTokenProvider.php
+++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
@@ -1,43 +1,23 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
use OC\Authentication\Exceptions\ExpiredTokenException;
use OC\Authentication\Exceptions\InvalidTokenException;
-use OC\Authentication\Exceptions\TokenPasswordExpiredException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
+use OC\Authentication\Exceptions\TokenPasswordExpiredException;
use OC\Authentication\Exceptions\WipeTokenException;
-use OCP\AppFramework\Db\TTransactional;
-use OCP\Cache\CappedMemoryCache;
use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\TTransactional;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Authentication\Token\IToken as OCPIToken;
+use OCP\ICache;
+use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUserManager;
@@ -46,6 +26,10 @@ use OCP\Security\IHasher;
use Psr\Log\LoggerInterface;
class PublicKeyTokenProvider implements IProvider {
+ public const TOKEN_MIN_LENGTH = 22;
+ /** Token cache TTL in seconds */
+ private const TOKEN_CACHE_TTL = 10;
+
use TTransactional;
/** @var PublicKeyTokenMapper */
@@ -65,18 +49,20 @@ class PublicKeyTokenProvider implements IProvider {
/** @var ITimeFactory */
private $time;
- /** @var CappedMemoryCache */
+ /** @var ICache */
private $cache;
- private IHasher $hasher;
+ /** @var IHasher */
+ private $hasher;
public function __construct(PublicKeyTokenMapper $mapper,
- ICrypto $crypto,
- IConfig $config,
- IDBConnection $db,
- LoggerInterface $logger,
- ITimeFactory $time,
- IHasher $hasher) {
+ ICrypto $crypto,
+ IConfig $config,
+ IDBConnection $db,
+ LoggerInterface $logger,
+ ITimeFactory $time,
+ IHasher $hasher,
+ ICacheFactory $cacheFactory) {
$this->mapper = $mapper;
$this->crypto = $crypto;
$this->config = $config;
@@ -84,7 +70,9 @@ class PublicKeyTokenProvider implements IProvider {
$this->logger = $logger;
$this->time = $time;
- $this->cache = new CappedMemoryCache();
+ $this->cache = $cacheFactory->isLocalCacheAvailable()
+ ? $cacheFactory->createLocal('authtoken_')
+ : $cacheFactory->createInMemory();
$this->hasher = $hasher;
}
@@ -92,78 +80,144 @@ class PublicKeyTokenProvider implements IProvider {
* {@inheritDoc}
*/
public function generateToken(string $token,
- string $uid,
- string $loginName,
- ?string $password,
- string $name,
- int $type = IToken::TEMPORARY_TOKEN,
- int $remember = IToken::DO_NOT_REMEMBER): IToken {
+ string $uid,
+ string $loginName,
+ ?string $password,
+ string $name,
+ int $type = OCPIToken::TEMPORARY_TOKEN,
+ int $remember = OCPIToken::DO_NOT_REMEMBER,
+ ?array $scope = null,
+ ): OCPIToken {
+ if (strlen($token) < self::TOKEN_MIN_LENGTH) {
+ $exception = new InvalidTokenException('Token is too short, minimum of ' . self::TOKEN_MIN_LENGTH . ' characters is required, ' . strlen($token) . ' characters given');
+ $this->logger->error('Invalid token provided when generating new token', ['exception' => $exception]);
+ throw $exception;
+ }
+
if (mb_strlen($name) > 128) {
$name = mb_substr($name, 0, 120) . '…';
}
+ // We need to check against one old token to see if there is a password
+ // hash that we can reuse for detecting outdated passwords
+ $randomOldToken = $this->mapper->getFirstTokenForUser($uid);
+ $oldTokenMatches = $randomOldToken && $randomOldToken->getPasswordHash() && $password !== null && $this->hasher->verify(sha1($password) . $password, $randomOldToken->getPasswordHash());
+
$dbToken = $this->newToken($token, $uid, $loginName, $password, $name, $type, $remember);
+
+ if ($oldTokenMatches) {
+ $dbToken->setPasswordHash($randomOldToken->getPasswordHash());
+ }
+
+ if ($scope !== null) {
+ $dbToken->setScope($scope);
+ }
+
$this->mapper->insert($dbToken);
+ if (!$oldTokenMatches && $password !== null) {
+ $this->updatePasswords($uid, $password);
+ }
+
// Add the token to the cache
- $this->cache[$dbToken->getToken()] = $dbToken;
+ $this->cacheToken($dbToken);
return $dbToken;
}
- public function getToken(string $tokenId): IToken {
+ public function getToken(string $tokenId): OCPIToken {
+ /**
+ * Token length: 72
+ * @see \OC\Core\Controller\ClientFlowLoginController::generateAppPassword
+ * @see \OC\Core\Controller\AppPasswordController::getAppPassword
+ * @see \OC\Core\Command\User\AddAppPassword::execute
+ * @see \OC\Core\Service\LoginFlowV2Service::flowDone
+ * @see \OCA\Talk\MatterbridgeManager::generatePassword
+ * @see \OCA\Preferred_Providers\Controller\PasswordController::generateAppPassword
+ * @see \OCA\GlobalSiteSelector\TokenHandler::generateAppPassword
+ *
+ * Token length: 22-256 - https://www.php.net/manual/en/session.configuration.php#ini.session.sid-length
+ * @see \OC\User\Session::createSessionToken
+ *
+ * Token length: 29
+ * @see \OCA\Settings\Controller\AuthSettingsController::generateRandomDeviceToken
+ * @see \OCA\Registration\Service\RegistrationService::generateAppPassword
+ */
+ if (strlen($tokenId) < self::TOKEN_MIN_LENGTH) {
+ throw new InvalidTokenException('Token is too short for a generated token, should be the password during basic auth');
+ }
+
$tokenHash = $this->hashToken($tokenId);
+ if ($token = $this->getTokenFromCache($tokenHash)) {
+ $this->checkToken($token);
+ return $token;
+ }
- if (isset($this->cache[$tokenHash])) {
- if ($this->cache[$tokenHash] instanceof DoesNotExistException) {
- $ex = $this->cache[$tokenHash];
- throw new InvalidTokenException("Token does not exist: " . $ex->getMessage(), 0, $ex);
- }
- $token = $this->cache[$tokenHash];
- } else {
+ try {
+ $token = $this->mapper->getToken($tokenHash);
+ $this->cacheToken($token);
+ } catch (DoesNotExistException $ex) {
try {
- $token = $this->mapper->getToken($this->hashToken($tokenId));
- $this->cache[$token->getToken()] = $token;
- } catch (DoesNotExistException $ex) {
- try {
- $token = $this->mapper->getToken($this->hashTokenWithEmptySecret($tokenId));
- $this->cache[$token->getToken()] = $token;
- $this->rotate($token, $tokenId, $tokenId);
- } catch (DoesNotExistException $ex2) {
- $this->cache[$tokenHash] = $ex2;
- throw new InvalidTokenException("Token does not exist: " . $ex->getMessage(), 0, $ex);
- }
+ $token = $this->mapper->getToken($this->hashTokenWithEmptySecret($tokenId));
+ $this->rotate($token, $tokenId, $tokenId);
+ } catch (DoesNotExistException) {
+ $this->cacheInvalidHash($tokenHash);
+ throw new InvalidTokenException('Token does not exist: ' . $ex->getMessage(), 0, $ex);
}
}
- if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
- throw new ExpiredTokenException($token);
- }
+ $this->checkToken($token);
- if ($token->getType() === IToken::WIPE_TOKEN) {
- throw new WipeTokenException($token);
+ return $token;
+ }
+
+ /**
+ * @throws InvalidTokenException when token doesn't exist
+ */
+ private function getTokenFromCache(string $tokenHash): ?PublicKeyToken {
+ $serializedToken = $this->cache->get($tokenHash);
+ if ($serializedToken === false) {
+ return null;
}
- if ($token->getPasswordInvalid() === true) {
- //The password is invalid we should throw an TokenPasswordExpiredException
- throw new TokenPasswordExpiredException($token);
+ if ($serializedToken === null) {
+ return null;
}
- return $token;
+ $token = unserialize($serializedToken, [
+ 'allowed_classes' => [PublicKeyToken::class],
+ ]);
+
+ return $token instanceof PublicKeyToken ? $token : null;
+ }
+
+ private function cacheToken(PublicKeyToken $token): void {
+ $this->cache->set($token->getToken(), serialize($token), self::TOKEN_CACHE_TTL);
}
- public function getTokenById(int $tokenId): IToken {
+ private function cacheInvalidHash(string $tokenHash): void {
+ // Invalid entries can be kept longer in cache since it’s unlikely to reuse them
+ $this->cache->set($tokenHash, false, self::TOKEN_CACHE_TTL * 2);
+ }
+
+ public function getTokenById(int $tokenId): OCPIToken {
try {
$token = $this->mapper->getTokenById($tokenId);
} catch (DoesNotExistException $ex) {
throw new InvalidTokenException("Token with ID $tokenId does not exist: " . $ex->getMessage(), 0, $ex);
}
+ $this->checkToken($token);
+
+ return $token;
+ }
+
+ private function checkToken($token): void {
if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
throw new ExpiredTokenException($token);
}
- if ($token->getType() === IToken::WIPE_TOKEN) {
+ if ($token->getType() === OCPIToken::WIPE_TOKEN) {
throw new WipeTokenException($token);
}
@@ -171,18 +225,14 @@ class PublicKeyTokenProvider implements IProvider {
//The password is invalid we should throw an TokenPasswordExpiredException
throw new TokenPasswordExpiredException($token);
}
-
- return $token;
}
- public function renewSessionToken(string $oldSessionId, string $sessionId): IToken {
- $this->cache->clear();
-
+ public function renewSessionToken(string $oldSessionId, string $sessionId): OCPIToken {
return $this->atomic(function () use ($oldSessionId, $sessionId) {
$token = $this->getToken($oldSessionId);
if (!($token instanceof PublicKeyToken)) {
- throw new InvalidTokenException("Invalid token type");
+ throw new InvalidTokenException('Invalid token type');
}
$password = null;
@@ -190,16 +240,21 @@ class PublicKeyTokenProvider implements IProvider {
$privateKey = $this->decrypt($token->getPrivateKey(), $oldSessionId);
$password = $this->decryptPassword($token->getPassword(), $privateKey);
}
+
+ $scope = $token->getScope() === '' ? null : $token->getScopeAsArray();
$newToken = $this->generateToken(
$sessionId,
$token->getUID(),
$token->getLoginName(),
$password,
$token->getName(),
- IToken::TEMPORARY_TOKEN,
- $token->getRemember()
+ OCPIToken::TEMPORARY_TOKEN,
+ $token->getRemember(),
+ $scope,
);
+ $this->cacheToken($newToken);
+ $this->cacheInvalidHash($token->getToken());
$this->mapper->delete($token);
return $newToken;
@@ -207,43 +262,55 @@ class PublicKeyTokenProvider implements IProvider {
}
public function invalidateToken(string $token) {
- $this->cache->clear();
-
+ $tokenHash = $this->hashToken($token);
$this->mapper->invalidate($this->hashToken($token));
$this->mapper->invalidate($this->hashTokenWithEmptySecret($token));
+ $this->cacheInvalidHash($tokenHash);
}
public function invalidateTokenById(string $uid, int $id) {
- $this->cache->clear();
+ $token = $this->mapper->getTokenById($id);
+ if ($token->getUID() !== $uid) {
+ return;
+ }
+ $this->mapper->invalidate($token->getToken());
+ $this->cacheInvalidHash($token->getToken());
- $this->mapper->deleteById($uid, $id);
}
public function invalidateOldTokens() {
- $this->cache->clear();
-
- $olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24);
+ $olderThan = $this->time->getTime() - $this->config->getSystemValueInt('session_lifetime', 60 * 60 * 24);
$this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan), ['app' => 'cron']);
- $this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER);
- $rememberThreshold = $this->time->getTime() - (int) $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
+ $this->mapper->invalidateOld($olderThan, OCPIToken::TEMPORARY_TOKEN, OCPIToken::DO_NOT_REMEMBER);
+
+ $rememberThreshold = $this->time->getTime() - $this->config->getSystemValueInt('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
$this->logger->debug('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold), ['app' => 'cron']);
- $this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER);
+ $this->mapper->invalidateOld($rememberThreshold, OCPIToken::TEMPORARY_TOKEN, OCPIToken::REMEMBER);
+
+ $wipeThreshold = $this->time->getTime() - $this->config->getSystemValueInt('token_auth_wipe_token_retention', 60 * 60 * 24 * 60);
+ $this->logger->debug('Invalidating auth tokens marked for remote wipe older than ' . date('c', $wipeThreshold), ['app' => 'cron']);
+ $this->mapper->invalidateOld($wipeThreshold, OCPIToken::WIPE_TOKEN);
+
+ $authTokenThreshold = $this->time->getTime() - $this->config->getSystemValueInt('token_auth_token_retention', 60 * 60 * 24 * 365);
+ $this->logger->debug('Invalidating auth tokens older than ' . date('c', $authTokenThreshold), ['app' => 'cron']);
+ $this->mapper->invalidateOld($authTokenThreshold, OCPIToken::PERMANENT_TOKEN);
}
- public function updateToken(IToken $token) {
- $this->cache->clear();
+ public function invalidateLastUsedBefore(string $uid, int $before): void {
+ $this->mapper->invalidateLastUsedBefore($uid, $before);
+ }
+ public function updateToken(OCPIToken $token) {
if (!($token instanceof PublicKeyToken)) {
- throw new InvalidTokenException("Invalid token type");
+ throw new InvalidTokenException('Invalid token type');
}
$this->mapper->update($token);
+ $this->cacheToken($token);
}
- public function updateTokenActivity(IToken $token) {
- $this->cache->clear();
-
+ public function updateTokenActivity(OCPIToken $token) {
if (!($token instanceof PublicKeyToken)) {
- throw new InvalidTokenException("Invalid token type");
+ throw new InvalidTokenException('Invalid token type');
}
$activityInterval = $this->config->getSystemValueInt('token_auth_activity_update', 60);
@@ -254,6 +321,7 @@ class PublicKeyTokenProvider implements IProvider {
if ($token->getLastActivity() < ($now - $activityInterval)) {
$token->setLastActivity($now);
$this->mapper->updateActivity($token, $now);
+ $this->cacheToken($token);
}
}
@@ -261,9 +329,9 @@ class PublicKeyTokenProvider implements IProvider {
return $this->mapper->getTokenByUser($uid);
}
- public function getPassword(IToken $savedToken, string $tokenId): string {
+ public function getPassword(OCPIToken $savedToken, string $tokenId): string {
if (!($savedToken instanceof PublicKeyToken)) {
- throw new InvalidTokenException("Invalid token type");
+ throw new InvalidTokenException('Invalid token type');
}
if ($savedToken->getPassword() === null) {
@@ -277,35 +345,34 @@ class PublicKeyTokenProvider implements IProvider {
return $this->decryptPassword($savedToken->getPassword(), $privateKey);
}
- public function setPassword(IToken $token, string $tokenId, string $password) {
- $this->cache->clear();
-
+ public function setPassword(OCPIToken $token, string $tokenId, string $password) {
if (!($token instanceof PublicKeyToken)) {
- throw new InvalidTokenException("Invalid token type");
+ throw new InvalidTokenException('Invalid token type');
}
- // When changing passwords all temp tokens are deleted
- $this->mapper->deleteTempToken($token);
+ $this->atomic(function () use ($password, $token) {
+ // When changing passwords all temp tokens are deleted
+ $this->mapper->deleteTempToken($token);
- // Update the password for all tokens
- $tokens = $this->mapper->getTokenByUser($token->getUID());
- foreach ($tokens as $t) {
- $publicKey = $t->getPublicKey();
- $t->setPassword($this->encryptPassword($password, $publicKey));
- $t->setPasswordHash($this->hashPassword($password));
- $this->updateToken($t);
- }
+ // Update the password for all tokens
+ $tokens = $this->mapper->getTokenByUser($token->getUID());
+ $hashedPassword = $this->hashPassword($password);
+ foreach ($tokens as $t) {
+ $publicKey = $t->getPublicKey();
+ $t->setPassword($this->encryptPassword($password, $publicKey));
+ $t->setPasswordHash($hashedPassword);
+ $this->updateToken($t);
+ }
+ }, $this->db);
}
private function hashPassword(string $password): string {
return $this->hasher->hash(sha1($password) . $password);
}
- public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
- $this->cache->clear();
-
+ public function rotate(OCPIToken $token, string $oldTokenId, string $newTokenId): OCPIToken {
if (!($token instanceof PublicKeyToken)) {
- throw new InvalidTokenException("Invalid token type");
+ throw new InvalidTokenException('Invalid token type');
}
// Decrypt private key with oldTokenId
@@ -320,7 +387,7 @@ class PublicKeyTokenProvider implements IProvider {
}
private function encrypt(string $plaintext, string $token): string {
- $secret = $this->config->getSystemValue('secret');
+ $secret = $this->config->getSystemValueString('secret');
return $this->crypto->encrypt($plaintext, $token . $secret);
}
@@ -328,7 +395,7 @@ class PublicKeyTokenProvider implements IProvider {
* @throws InvalidTokenException
*/
private function decrypt(string $cipherText, string $token): string {
- $secret = $this->config->getSystemValue('secret');
+ $secret = $this->config->getSystemValueString('secret');
try {
return $this->crypto->decrypt($cipherText, $token . $secret);
} catch (\Exception $ex) {
@@ -338,7 +405,7 @@ class PublicKeyTokenProvider implements IProvider {
} catch (\Exception $ex2) {
// Delete the invalid token
$this->invalidateToken($token);
- throw new InvalidTokenException("Could not decrypt token password: " . $ex->getMessage(), 0, $ex2);
+ throw new InvalidTokenException('Could not decrypt token password: ' . $ex->getMessage(), 0, $ex2);
}
}
}
@@ -358,12 +425,12 @@ class PublicKeyTokenProvider implements IProvider {
}
private function hashToken(string $token): string {
- $secret = $this->config->getSystemValue('secret');
+ $secret = $this->config->getSystemValueString('secret');
return hash('sha512', $token . $secret);
}
/**
- * @deprecated Fallback for instances where the secret might not have been set by accident
+ * @deprecated 26.0.0 Fallback for instances where the secret might not have been set by accident
*/
private function hashTokenWithEmptySecret(string $token): string {
return hash('sha512', $token);
@@ -373,12 +440,12 @@ class PublicKeyTokenProvider implements IProvider {
* @throws \RuntimeException when OpenSSL reports a problem
*/
private function newToken(string $token,
- string $uid,
- string $loginName,
- $password,
- string $name,
- int $type,
- int $remember): PublicKeyToken {
+ string $uid,
+ string $loginName,
+ $password,
+ string $name,
+ int $type,
+ int $remember): PublicKeyToken {
$dbToken = new PublicKeyToken();
$dbToken->setUid($uid);
$dbToken->setLoginName($loginName);
@@ -426,61 +493,67 @@ class PublicKeyTokenProvider implements IProvider {
return $dbToken;
}
- public function markPasswordInvalid(IToken $token, string $tokenId) {
- $this->cache->clear();
-
+ public function markPasswordInvalid(OCPIToken $token, string $tokenId) {
if (!($token instanceof PublicKeyToken)) {
- throw new InvalidTokenException("Invalid token type");
+ throw new InvalidTokenException('Invalid token type');
}
$token->setPasswordInvalid(true);
$this->mapper->update($token);
+ $this->cacheToken($token);
}
public function updatePasswords(string $uid, string $password) {
- $this->cache->clear();
-
// prevent setting an empty pw as result of pw-less-login
if ($password === '' || !$this->config->getSystemValueBool('auth.storeCryptedPassword', true)) {
return;
}
- // Update the password for all tokens
- $tokens = $this->mapper->getTokenByUser($uid);
- $newPasswordHash = null;
-
- /**
- * - true: The password hash could not be verified anymore
- * and the token needs to be updated with the newly encrypted password
- * - false: The hash could still be verified
- * - missing: The hash needs to be verified
- */
- $hashNeedsUpdate = [];
-
- foreach ($tokens as $t) {
- if (!isset($hashNeedsUpdate[$t->getPasswordHash()])) {
- if ($t->getPasswordHash() === null) {
- $hashNeedsUpdate[$t->getPasswordHash() ?: ''] = true;
- } elseif (!$this->hasher->verify(sha1($password) . $password, $t->getPasswordHash())) {
- $hashNeedsUpdate[$t->getPasswordHash() ?: ''] = true;
- } else {
- $hashNeedsUpdate[$t->getPasswordHash() ?: ''] = false;
+ $this->atomic(function () use ($password, $uid) {
+ // Update the password for all tokens
+ $tokens = $this->mapper->getTokenByUser($uid);
+ $newPasswordHash = null;
+
+ /**
+ * - true: The password hash could not be verified anymore
+ * and the token needs to be updated with the newly encrypted password
+ * - false: The hash could still be verified
+ * - missing: The hash needs to be verified
+ */
+ $hashNeedsUpdate = [];
+
+ foreach ($tokens as $t) {
+ if (!isset($hashNeedsUpdate[$t->getPasswordHash()])) {
+ if ($t->getPasswordHash() === null) {
+ $hashNeedsUpdate[$t->getPasswordHash() ?: ''] = true;
+ } elseif (!$this->hasher->verify(sha1($password) . $password, $t->getPasswordHash())) {
+ $hashNeedsUpdate[$t->getPasswordHash() ?: ''] = true;
+ } else {
+ $hashNeedsUpdate[$t->getPasswordHash() ?: ''] = false;
+ }
}
- }
- $needsUpdating = $hashNeedsUpdate[$t->getPasswordHash() ?: ''] ?? true;
-
- if ($needsUpdating) {
- if ($newPasswordHash === null) {
- $newPasswordHash = $this->hashPassword($password);
+ $needsUpdating = $hashNeedsUpdate[$t->getPasswordHash() ?: ''] ?? true;
+
+ if ($needsUpdating) {
+ if ($newPasswordHash === null) {
+ $newPasswordHash = $this->hashPassword($password);
+ }
+
+ $publicKey = $t->getPublicKey();
+ $t->setPassword($this->encryptPassword($password, $publicKey));
+ $t->setPasswordHash($newPasswordHash);
+ $t->setPasswordInvalid(false);
+ $this->updateToken($t);
}
+ }
- $publicKey = $t->getPublicKey();
- $t->setPassword($this->encryptPassword($password, $publicKey));
- $t->setPasswordHash($newPasswordHash);
- $t->setPasswordInvalid(false);
- $this->updateToken($t);
+ // If password hashes are different we update them all to be equal so
+ // that the next execution only needs to verify once
+ if (count($hashNeedsUpdate) > 1) {
+ $newPasswordHash = $this->hashPassword($password);
+ $this->mapper->updateHashesForUser($uid, $newPasswordHash);
}
- }
+ }, $this->db);
}
private function logOpensslError() {
diff --git a/lib/private/Authentication/Token/RemoteWipe.php b/lib/private/Authentication/Token/RemoteWipe.php
index 5fd01cfbe87..80ba330b66d 100644
--- a/lib/private/Authentication/Token/RemoteWipe.php
+++ b/lib/private/Authentication/Token/RemoteWipe.php
@@ -3,38 +3,19 @@
declare(strict_types=1);
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\Token;
-use Psr\Log\LoggerInterface;
-use function array_filter;
use OC\Authentication\Events\RemoteWipeFinished;
use OC\Authentication\Events\RemoteWipeStarted;
-use OC\Authentication\Exceptions\InvalidTokenException;
-use OC\Authentication\Exceptions\WipeTokenException;
+use OCP\Authentication\Exceptions\InvalidTokenException;
+use OCP\Authentication\Exceptions\WipeTokenException;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUser;
+use Psr\Log\LoggerInterface;
+use function array_filter;
class RemoteWipe {
/** @var IProvider */
@@ -47,8 +28,8 @@ class RemoteWipe {
private $logger;
public function __construct(IProvider $tokenProvider,
- IEventDispatcher $eventDispatcher,
- LoggerInterface $logger) {
+ IEventDispatcher $eventDispatcher,
+ LoggerInterface $logger) {
$this->tokenProvider = $tokenProvider;
$this->eventDispatcher = $eventDispatcher;
$this->logger = $logger;
@@ -117,7 +98,7 @@ class RemoteWipe {
$dbToken = $e->getToken();
- $this->logger->info("user " . $dbToken->getUID() . " started a remote wipe");
+ $this->logger->info('user ' . $dbToken->getUID() . ' started a remote wipe');
$this->eventDispatcher->dispatch(RemoteWipeStarted::class, new RemoteWipeStarted($dbToken));
@@ -145,7 +126,7 @@ class RemoteWipe {
$this->tokenProvider->invalidateToken($token);
- $this->logger->info("user " . $dbToken->getUID() . " finished a remote wipe");
+ $this->logger->info('user ' . $dbToken->getUID() . ' finished a remote wipe');
$this->eventDispatcher->dispatch(RemoteWipeFinished::class, new RemoteWipeFinished($dbToken));
return true;
diff --git a/lib/private/Authentication/Token/TokenCleanupJob.php b/lib/private/Authentication/Token/TokenCleanupJob.php
index 292f8f310e8..e6d1e69e9b4 100644
--- a/lib/private/Authentication/Token/TokenCleanupJob.php
+++ b/lib/private/Authentication/Token/TokenCleanupJob.php
@@ -1,23 +1,8 @@
<?php
+
/**
- * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
- *
- * @author Thomas Citharel <nextcloud@tcit.fr>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\Token;
diff --git a/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php b/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php
index 19d80218562..cc468dbeba0 100644
--- a/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php
+++ b/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php
@@ -3,30 +3,11 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth\Db;
-use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
-use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use function array_map;
@@ -48,7 +29,7 @@ class ProviderUserAssignmentDao {
* Get all assigned provider IDs for the given user ID
*
* @return array<string, bool> where the array key is the provider ID (string) and the
- * value is the enabled state (bool)
+ * value is the enabled state (bool)
*/
public function getState(string $uid): array {
$qb = $this->conn->getQueryBuilder();
@@ -56,10 +37,10 @@ class ProviderUserAssignmentDao {
$query = $qb->select('provider_id', 'enabled')
->from(self::TABLE_NAME)
->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
- $result = $query->execute();
+ $result = $query->executeQuery();
$providers = [];
foreach ($result->fetchAll() as $row) {
- $providers[(string)$row['provider_id']] = 1 === (int)$row['enabled'];
+ $providers[(string)$row['provider_id']] = (int)$row['enabled'] === 1;
}
$result->closeCursor();
@@ -69,41 +50,38 @@ class ProviderUserAssignmentDao {
/**
* Persist a new/updated (provider_id, uid, enabled) tuple
*/
- public function persist(string $providerId, string $uid, int $enabled) {
- $qb = $this->conn->getQueryBuilder();
-
- try {
- // Insert a new entry
- $insertQuery = $qb->insert(self::TABLE_NAME)->values([
- 'provider_id' => $qb->createNamedParameter($providerId),
- 'uid' => $qb->createNamedParameter($uid),
- 'enabled' => $qb->createNamedParameter($enabled, IQueryBuilder::PARAM_INT),
- ]);
-
- $insertQuery->execute();
- } catch (UniqueConstraintViolationException $ex) {
- // There is already an entry -> update it
- $updateQuery = $qb->update(self::TABLE_NAME)
- ->set('enabled', $qb->createNamedParameter($enabled))
- ->where($qb->expr()->eq('provider_id', $qb->createNamedParameter($providerId)))
- ->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
- $updateQuery->execute();
+ public function persist(string $providerId, string $uid, int $enabled): void {
+ $conn = $this->conn;
+
+ // Insert a new entry
+ if ($conn->insertIgnoreConflict(self::TABLE_NAME, [
+ 'provider_id' => $providerId,
+ 'uid' => $uid,
+ 'enabled' => $enabled,
+ ])) {
+ return;
}
+
+ // There is already an entry -> update it
+ $qb = $conn->getQueryBuilder();
+ $updateQuery = $qb->update(self::TABLE_NAME)
+ ->set('enabled', $qb->createNamedParameter($enabled))
+ ->where($qb->expr()->eq('provider_id', $qb->createNamedParameter($providerId)))
+ ->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
+ $updateQuery->executeStatement();
}
/**
* Delete all provider states of a user and return the provider IDs
*
- * @param string $uid
- *
- * @return int[]
+ * @return list<array{provider_id: string, uid: string, enabled: bool}>
*/
public function deleteByUser(string $uid): array {
$qb1 = $this->conn->getQueryBuilder();
$selectQuery = $qb1->select('*')
->from(self::TABLE_NAME)
->where($qb1->expr()->eq('uid', $qb1->createNamedParameter($uid)));
- $selectResult = $selectQuery->execute();
+ $selectResult = $selectQuery->executeQuery();
$rows = $selectResult->fetchAll();
$selectResult->closeCursor();
@@ -111,23 +89,23 @@ class ProviderUserAssignmentDao {
$deleteQuery = $qb2
->delete(self::TABLE_NAME)
->where($qb2->expr()->eq('uid', $qb2->createNamedParameter($uid)));
- $deleteQuery->execute();
+ $deleteQuery->executeStatement();
- return array_map(function (array $row) {
+ return array_values(array_map(function (array $row) {
return [
- 'provider_id' => $row['provider_id'],
- 'uid' => $row['uid'],
- 'enabled' => 1 === (int) $row['enabled'],
+ 'provider_id' => (string)$row['provider_id'],
+ 'uid' => (string)$row['uid'],
+ 'enabled' => ((int)$row['enabled']) === 1,
];
- }, $rows);
+ }, $rows));
}
- public function deleteAll(string $providerId) {
+ public function deleteAll(string $providerId): void {
$qb = $this->conn->getQueryBuilder();
$deleteQuery = $qb->delete(self::TABLE_NAME)
->where($qb->expr()->eq('provider_id', $qb->createNamedParameter($providerId)));
- $deleteQuery->execute();
+ $deleteQuery->executeStatement();
}
}
diff --git a/lib/private/Authentication/TwoFactorAuth/EnforcementState.php b/lib/private/Authentication/TwoFactorAuth/EnforcementState.php
index b95128c1e0f..e02064bc8f7 100644
--- a/lib/private/Authentication/TwoFactorAuth/EnforcementState.php
+++ b/lib/private/Authentication/TwoFactorAuth/EnforcementState.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
@@ -45,8 +28,8 @@ class EnforcementState implements JsonSerializable {
* @param string[] $excludedGroups
*/
public function __construct(bool $enforced,
- array $enforcedGroups = [],
- array $excludedGroups = []) {
+ array $enforcedGroups = [],
+ array $excludedGroups = []) {
$this->enforced = $enforced;
$this->enforcedGroups = $enforcedGroups;
$this->excludedGroups = $excludedGroups;
diff --git a/lib/private/Authentication/TwoFactorAuth/Manager.php b/lib/private/Authentication/TwoFactorAuth/Manager.php
index d62556465df..07aa98610ed 100644
--- a/lib/private/Authentication/TwoFactorAuth/Manager.php
+++ b/lib/private/Authentication/TwoFactorAuth/Manager.php
@@ -1,41 +1,25 @@
<?php
declare(strict_types=1);
-
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Authentication\TwoFactorAuth;
use BadMethodCallException;
use Exception;
-use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Token\IProvider as TokenProvider;
use OCP\Activity\IManager;
+use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Authentication\Exceptions\InvalidTokenException;
use OCP\Authentication\TwoFactorAuth\IActivatableAtLogin;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Authentication\TwoFactorAuth\IRegistry;
+use OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengeFailed;
+use OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengePassed;
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserDisabled;
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserEnabled;
use OCP\EventDispatcher\IEventDispatcher;
@@ -44,8 +28,6 @@ use OCP\ISession;
use OCP\IUser;
use OCP\Session\Exceptions\SessionNotAvailableException;
use Psr\Log\LoggerInterface;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-use Symfony\Component\EventDispatcher\GenericEvent;
use function array_diff;
use function array_filter;
@@ -85,23 +67,19 @@ class Manager {
/** @var IEventDispatcher */
private $dispatcher;
- /** @var EventDispatcherInterface */
- private $legacyDispatcher;
-
/** @psalm-var array<string, bool> */
private $userIsTwoFactorAuthenticated = [];
public function __construct(ProviderLoader $providerLoader,
- IRegistry $providerRegistry,
- MandatoryTwoFactor $mandatoryTwoFactor,
- ISession $session,
- IConfig $config,
- IManager $activityManager,
- LoggerInterface $logger,
- TokenProvider $tokenProvider,
- ITimeFactory $timeFactory,
- IEventDispatcher $eventDispatcher,
- EventDispatcherInterface $legacyDispatcher) {
+ IRegistry $providerRegistry,
+ MandatoryTwoFactor $mandatoryTwoFactor,
+ ISession $session,
+ IConfig $config,
+ IManager $activityManager,
+ LoggerInterface $logger,
+ TokenProvider $tokenProvider,
+ ITimeFactory $timeFactory,
+ IEventDispatcher $eventDispatcher) {
$this->providerLoader = $providerLoader;
$this->providerRegistry = $providerRegistry;
$this->mandatoryTwoFactor = $mandatoryTwoFactor;
@@ -112,14 +90,10 @@ class Manager {
$this->tokenProvider = $tokenProvider;
$this->timeFactory = $timeFactory;
$this->dispatcher = $eventDispatcher;
- $this->legacyDispatcher = $legacyDispatcher;
}
/**
* Determine whether the user must provide a second factor challenge
- *
- * @param IUser $user
- * @return boolean
*/
public function isTwoFactorAuthenticated(IUser $user): bool {
if (isset($this->userIsTwoFactorAuthenticated[$user->getUID()])) {
@@ -143,18 +117,13 @@ class Manager {
/**
* Get a 2FA provider by its ID
- *
- * @param IUser $user
- * @param string $challengeProviderId
- * @return IProvider|null
*/
- public function getProvider(IUser $user, string $challengeProviderId) {
+ public function getProvider(IUser $user, string $challengeProviderId): ?IProvider {
$providers = $this->getProviderSet($user)->getProviders();
return $providers[$challengeProviderId] ?? null;
}
/**
- * @param IUser $user
* @return IActivatableAtLogin[]
* @throws Exception
*/
@@ -224,7 +193,7 @@ class Manager {
if (!empty($missing)) {
// There was at least one provider missing
- $this->logger->alert(count($missing) . " two-factor auth providers failed to load", ['app' => 'core']);
+ $this->logger->alert(count($missing) . ' two-factor auth providers failed to load', ['app' => 'core']);
return true;
}
@@ -280,21 +249,17 @@ class Manager {
$sessionId = $this->session->getId();
$token = $this->tokenProvider->getToken($sessionId);
$tokenId = $token->getId();
- $this->config->deleteUserValue($user->getUID(), 'login_token_2fa', $tokenId);
-
- $dispatchEvent = new GenericEvent($user, ['provider' => $provider->getDisplayName()]);
- $this->legacyDispatcher->dispatch(IProvider::EVENT_SUCCESS, $dispatchEvent);
+ $this->config->deleteUserValue($user->getUID(), 'login_token_2fa', (string)$tokenId);
$this->dispatcher->dispatchTyped(new TwoFactorProviderForUserEnabled($user, $provider));
+ $this->dispatcher->dispatchTyped(new TwoFactorProviderChallengePassed($user, $provider));
$this->publishEvent($user, 'twofactor_success', [
'provider' => $provider->getDisplayName(),
]);
} else {
- $dispatchEvent = new GenericEvent($user, ['provider' => $provider->getDisplayName()]);
- $this->legacyDispatcher->dispatch(IProvider::EVENT_FAILED, $dispatchEvent);
-
$this->dispatcher->dispatchTyped(new TwoFactorProviderForUserDisabled($user, $provider));
+ $this->dispatcher->dispatchTyped(new TwoFactorProviderChallengeFailed($user, $provider));
$this->publishEvent($user, 'twofactor_failed', [
'provider' => $provider->getDisplayName(),
@@ -330,21 +295,21 @@ class Manager {
* @param IUser $user the currently logged in user
* @return boolean
*/
- public function needsSecondFactor(IUser $user = null): bool {
+ public function needsSecondFactor(?IUser $user = null): bool {
if ($user === null) {
return false;
}
- // If we are authenticated using an app password skip all this
- if ($this->session->exists('app_password')) {
+ // If we are authenticated using an app password or AppAPI Auth, skip all this
+ if ($this->session->exists('app_password') || $this->session->get('app_api') === true) {
return false;
}
// First check if the session tells us we should do 2FA (99% case)
if (!$this->session->exists(self::SESSION_UID_KEY)) {
// Check if the session tells us it is 2FA authenticated already
- if ($this->session->exists(self::SESSION_UID_DONE) &&
- $this->session->get(self::SESSION_UID_DONE) === $user->getUID()) {
+ if ($this->session->exists(self::SESSION_UID_DONE)
+ && $this->session->get(self::SESSION_UID_DONE) === $user->getUID()) {
return false;
}
@@ -358,7 +323,7 @@ class Manager {
$tokenId = $token->getId();
$tokensNeeding2FA = $this->config->getUserKeys($user->getUID(), 'login_token_2fa');
- if (!\in_array((string) $tokenId, $tokensNeeding2FA, true)) {
+ if (!\in_array((string)$tokenId, $tokensNeeding2FA, true)) {
$this->session->set(self::SESSION_UID_DONE, $user->getUID());
return false;
}
@@ -395,14 +360,19 @@ class Manager {
$id = $this->session->getId();
$token = $this->tokenProvider->getToken($id);
- $this->config->setUserValue($user->getUID(), 'login_token_2fa', (string) $token->getId(), $this->timeFactory->getTime());
+ $this->config->setUserValue($user->getUID(), 'login_token_2fa', (string)$token->getId(), (string)$this->timeFactory->getTime());
}
public function clearTwoFactorPending(string $userId) {
$tokensNeeding2FA = $this->config->getUserKeys($userId, 'login_token_2fa');
foreach ($tokensNeeding2FA as $tokenId) {
- $this->tokenProvider->invalidateTokenById($userId, (int)$tokenId);
+ $this->config->deleteUserValue($userId, 'login_token_2fa', $tokenId);
+
+ try {
+ $this->tokenProvider->invalidateTokenById($userId, (int)$tokenId);
+ } catch (DoesNotExistException $e) {
+ }
}
}
}
diff --git a/lib/private/Authentication/TwoFactorAuth/MandatoryTwoFactor.php b/lib/private/Authentication/TwoFactorAuth/MandatoryTwoFactor.php
index 3bfbd77941b..37c9d3fc550 100644
--- a/lib/private/Authentication/TwoFactorAuth/MandatoryTwoFactor.php
+++ b/lib/private/Authentication/TwoFactorAuth/MandatoryTwoFactor.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
diff --git a/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php b/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php
index 25cdc387f61..7e674a01dd8 100644
--- a/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php
+++ b/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php
@@ -3,32 +3,13 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
use Exception;
-use OC;
-use OC_App;
+use OC\AppFramework\Bootstrap\Coordinator;
use OCP\App\IAppManager;
use OCP\AppFramework\QueryException;
use OCP\Authentication\TwoFactorAuth\IProvider;
@@ -37,15 +18,10 @@ use OCP\IUser;
class ProviderLoader {
public const BACKUP_CODES_APP_ID = 'twofactor_backupcodes';
- /** @var IAppManager */
- private $appManager;
-
- /** @var OC\AppFramework\Bootstrap\Coordinator */
- private $coordinator;
-
- public function __construct(IAppManager $appManager, OC\AppFramework\Bootstrap\Coordinator $coordinator) {
- $this->appManager = $appManager;
- $this->coordinator = $coordinator;
+ public function __construct(
+ private IAppManager $appManager,
+ private Coordinator $coordinator,
+ ) {
}
/**
@@ -66,7 +42,7 @@ class ProviderLoader {
foreach ($providerClasses as $class) {
try {
$this->loadTwoFactorApp($appId);
- $provider = OC::$server->query($class);
+ $provider = \OCP\Server::get($class);
$providers[$provider->getId()] = $provider;
} catch (QueryException $exc) {
// Provider class can not be resolved
@@ -76,12 +52,12 @@ class ProviderLoader {
}
}
- $registeredProviders = $this->coordinator->getRegistrationContext()->getTwoFactorProviders();
+ $registeredProviders = $this->coordinator->getRegistrationContext()?->getTwoFactorProviders() ?? [];
foreach ($registeredProviders as $provider) {
try {
$this->loadTwoFactorApp($provider->getAppId());
- $provider = OC::$server->query($provider->getService());
- $providers[$provider->getId()] = $provider;
+ $providerInstance = \OCP\Server::get($provider->getService());
+ $providers[$providerInstance->getId()] = $providerInstance;
} catch (QueryException $exc) {
// Provider class can not be resolved
throw new Exception('Could not load two-factor auth provider ' . $provider->getService());
@@ -93,12 +69,10 @@ class ProviderLoader {
/**
* Load an app by ID if it has not been loaded yet
- *
- * @param string $appId
*/
- protected function loadTwoFactorApp(string $appId) {
- if (!OC_App::isAppLoaded($appId)) {
- OC_App::loadApp($appId);
+ protected function loadTwoFactorApp(string $appId): void {
+ if (!$this->appManager->isAppLoaded($appId)) {
+ $this->appManager->loadApp($appId);
}
}
}
diff --git a/lib/private/Authentication/TwoFactorAuth/ProviderManager.php b/lib/private/Authentication/TwoFactorAuth/ProviderManager.php
index c7c075bdab3..5ce4c598154 100644
--- a/lib/private/Authentication/TwoFactorAuth/ProviderManager.php
+++ b/lib/private/Authentication/TwoFactorAuth/ProviderManager.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
diff --git a/lib/private/Authentication/TwoFactorAuth/ProviderSet.php b/lib/private/Authentication/TwoFactorAuth/ProviderSet.php
index af270fb83c8..15b82be6dec 100644
--- a/lib/private/Authentication/TwoFactorAuth/ProviderSet.php
+++ b/lib/private/Authentication/TwoFactorAuth/ProviderSet.php
@@ -3,31 +3,14 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
-use function array_filter;
use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider;
use OCP\Authentication\TwoFactorAuth\IProvider;
+use function array_filter;
/**
* Contains all two-factor provider information for the two-factor login challenge
diff --git a/lib/private/Authentication/TwoFactorAuth/Registry.php b/lib/private/Authentication/TwoFactorAuth/Registry.php
index 6c82572578c..544f60c4f97 100644
--- a/lib/private/Authentication/TwoFactorAuth/Registry.php
+++ b/lib/private/Authentication/TwoFactorAuth/Registry.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\TwoFactorAuth;
@@ -31,6 +13,9 @@ use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Authentication\TwoFactorAuth\IRegistry;
use OCP\Authentication\TwoFactorAuth\RegistryEvent;
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderDisabled;
+use OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserRegistered;
+use OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserUnregistered;
+use OCP\Authentication\TwoFactorAuth\TwoFactorProviderUserDeleted;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUser;
@@ -42,7 +27,7 @@ class Registry implements IRegistry {
private $dispatcher;
public function __construct(ProviderUserAssignmentDao $assignmentDao,
- IEventDispatcher $dispatcher) {
+ IEventDispatcher $dispatcher) {
$this->assignmentDao = $assignmentDao;
$this->dispatcher = $dispatcher;
}
@@ -56,6 +41,7 @@ class Registry implements IRegistry {
$event = new RegistryEvent($provider, $user);
$this->dispatcher->dispatch(self::EVENT_PROVIDER_ENABLED, $event);
+ $this->dispatcher->dispatchTyped(new TwoFactorProviderForUserRegistered($user, $provider));
}
public function disableProviderFor(IProvider $provider, IUser $user) {
@@ -63,12 +49,14 @@ class Registry implements IRegistry {
$event = new RegistryEvent($provider, $user);
$this->dispatcher->dispatch(self::EVENT_PROVIDER_DISABLED, $event);
+ $this->dispatcher->dispatchTyped(new TwoFactorProviderForUserUnregistered($user, $provider));
}
public function deleteUserData(IUser $user): void {
foreach ($this->assignmentDao->deleteByUser($user->getUID()) as $provider) {
$event = new TwoFactorProviderDisabled($provider['provider_id']);
$this->dispatcher->dispatchTyped($event);
+ $this->dispatcher->dispatchTyped(new TwoFactorProviderUserDeleted($user, $provider['provider_id']));
}
}
diff --git a/lib/private/Authentication/WebAuthn/CredentialRepository.php b/lib/private/Authentication/WebAuthn/CredentialRepository.php
index e5c3fcf1618..203f2ef9020 100644
--- a/lib/private/Authentication/WebAuthn/CredentialRepository.php
+++ b/lib/private/Authentication/WebAuthn/CredentialRepository.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\WebAuthn;
@@ -61,7 +44,7 @@ class CredentialRepository implements PublicKeyCredentialSourceRepository {
}, $entities);
}
- public function saveAndReturnCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource, string $name = null): PublicKeyCredentialEntity {
+ public function saveAndReturnCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource, ?string $name = null, bool $userVerification = false): PublicKeyCredentialEntity {
$oldEntity = null;
try {
@@ -75,19 +58,24 @@ class CredentialRepository implements PublicKeyCredentialSourceRepository {
$name = 'default';
}
- $entity = PublicKeyCredentialEntity::fromPublicKeyCrendentialSource($name, $publicKeyCredentialSource);
+ $entity = PublicKeyCredentialEntity::fromPublicKeyCrendentialSource($name, $publicKeyCredentialSource, $userVerification);
if ($oldEntity) {
$entity->setId($oldEntity->getId());
if ($defaultName) {
$entity->setName($oldEntity->getName());
}
+
+ // Don't downgrade UV just because it was skipped during a login due to another key
+ if ($oldEntity->getUserVerification()) {
+ $entity->setUserVerification(true);
+ }
}
return $this->credentialMapper->insertOrUpdate($entity);
}
- public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource, string $name = null): void {
+ public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource, ?string $name = null): void {
$this->saveAndReturnCredentialSource($publicKeyCredentialSource, $name);
}
}
diff --git a/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialEntity.php b/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialEntity.php
index 6f97ded483d..6c4bc3ca81b 100644
--- a/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialEntity.php
+++ b/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialEntity.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\WebAuthn\Db;
@@ -41,6 +23,10 @@ use Webauthn\PublicKeyCredentialSource;
* @method void setPublicKeyCredentialId(string $id);
* @method string getData();
* @method void setData(string $data);
+ *
+ * @since 30.0.0 Add userVerification attribute
+ * @method bool|null getUserVerification();
+ * @method void setUserVerification(bool $userVerification);
*/
class PublicKeyCredentialEntity extends Entity implements JsonSerializable {
/** @var string */
@@ -55,20 +41,25 @@ class PublicKeyCredentialEntity extends Entity implements JsonSerializable {
/** @var string */
protected $data;
+ /** @var bool|null */
+ protected $userVerification;
+
public function __construct() {
$this->addType('name', 'string');
$this->addType('uid', 'string');
$this->addType('publicKeyCredentialId', 'string');
$this->addType('data', 'string');
+ $this->addType('userVerification', 'boolean');
}
- public static function fromPublicKeyCrendentialSource(string $name, PublicKeyCredentialSource $publicKeyCredentialSource): PublicKeyCredentialEntity {
+ public static function fromPublicKeyCrendentialSource(string $name, PublicKeyCredentialSource $publicKeyCredentialSource, bool $userVerification): PublicKeyCredentialEntity {
$publicKeyCredentialEntity = new self();
$publicKeyCredentialEntity->setName($name);
$publicKeyCredentialEntity->setUid($publicKeyCredentialSource->getUserHandle());
$publicKeyCredentialEntity->setPublicKeyCredentialId(base64_encode($publicKeyCredentialSource->getPublicKeyCredentialId()));
$publicKeyCredentialEntity->setData(json_encode($publicKeyCredentialSource));
+ $publicKeyCredentialEntity->setUserVerification($userVerification);
return $publicKeyCredentialEntity;
}
diff --git a/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialMapper.php b/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialMapper.php
index 72c557eb53a..fa7304157c8 100644
--- a/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialMapper.php
+++ b/lib/private/Authentication/WebAuthn/Db/PublicKeyCredentialMapper.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\WebAuthn\Db;
diff --git a/lib/private/Authentication/WebAuthn/Manager.php b/lib/private/Authentication/WebAuthn/Manager.php
index 744a3fa354a..96dc0719b54 100644
--- a/lib/private/Authentication/WebAuthn/Manager.php
+++ b/lib/private/Authentication/WebAuthn/Manager.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Authentication\WebAuthn;
@@ -72,7 +53,7 @@ class Manager {
CredentialRepository $repository,
PublicKeyCredentialMapper $credentialMapper,
LoggerInterface $logger,
- IConfig $config
+ IConfig $config,
) {
$this->repository = $repository;
$this->credentialMapper = $credentialMapper;
@@ -83,15 +64,15 @@ class Manager {
public function startRegistration(IUser $user, string $serverHost): PublicKeyCredentialCreationOptions {
$rpEntity = new PublicKeyCredentialRpEntity(
'Nextcloud', //Name
- $this->stripPort($serverHost), //ID
+ $this->stripPort($serverHost), //ID
null //Icon
);
$userEntity = new PublicKeyCredentialUserEntity(
- $user->getUID(), //Name
- $user->getUID(), //ID
- $user->getDisplayName() //Display name
-// 'https://foo.example.co/avatar/123e4567-e89b-12d3-a456-426655440000' //Icon
+ $user->getUID(), // Name
+ $user->getUID(), // ID
+ $user->getDisplayName() // Display name
+ // 'https://foo.example.co/avatar/123e4567-e89b-12d3-a456-426655440000' //Icon
);
$challenge = random_bytes(32);
@@ -107,9 +88,10 @@ class Manager {
];
$authenticatorSelectionCriteria = new AuthenticatorSelectionCriteria(
+ AuthenticatorSelectionCriteria::AUTHENTICATOR_ATTACHMENT_NO_PREFERENCE,
+ AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_PREFERRED,
null,
false,
- AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_DISCOURAGED
);
return new PublicKeyCredentialCreationOptions(
@@ -117,11 +99,10 @@ class Manager {
$userEntity,
$challenge,
$publicKeyCredentialParametersList,
- $timeout,
- $excludedPublicKeyDescriptors,
$authenticatorSelectionCriteria,
PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE,
- null
+ $excludedPublicKeyDescriptors,
+ $timeout,
);
}
@@ -149,7 +130,7 @@ class Manager {
try {
// Load the data
$publicKeyCredential = $publicKeyCredentialLoader->load($data);
- $response = $publicKeyCredential->getResponse();
+ $response = $publicKeyCredential->response;
// Check if the response is an Authenticator Attestation Response
if (!$response instanceof AuthenticatorAttestationResponse) {
@@ -162,13 +143,16 @@ class Manager {
$publicKeyCredentialSource = $authenticatorAttestationResponseValidator->check(
$response,
$publicKeyCredentialCreationOptions,
- $request);
+ $request,
+ ['localhost'],
+ );
} catch (\Throwable $exception) {
throw $exception;
}
// Persist the data
- return $this->repository->saveAndReturnCredentialSource($publicKeyCredentialSource, $name);
+ $userVerification = $response->attestationObject->authData->isUserVerified();
+ return $this->repository->saveAndReturnCredentialSource($publicKeyCredentialSource, $name, $userVerification);
}
private function stripPort(string $serverHost): string {
@@ -177,21 +161,25 @@ class Manager {
public function startAuthentication(string $uid, string $serverHost): PublicKeyCredentialRequestOptions {
// List of registered PublicKeyCredentialDescriptor classes associated to the user
- $registeredPublicKeyCredentialDescriptors = array_map(function (PublicKeyCredentialEntity $entity) {
+ $userVerificationRequirement = AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED;
+ $registeredPublicKeyCredentialDescriptors = array_map(function (PublicKeyCredentialEntity $entity) use (&$userVerificationRequirement) {
+ if ($entity->getUserVerification() !== true) {
+ $userVerificationRequirement = AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_DISCOURAGED;
+ }
$credential = $entity->toPublicKeyCredentialSource();
return new PublicKeyCredentialDescriptor(
- $credential->getType(),
- $credential->getPublicKeyCredentialId()
+ $credential->type,
+ $credential->publicKeyCredentialId,
);
}, $this->credentialMapper->findAllForUid($uid));
// Public Key Credential Request Options
return new PublicKeyCredentialRequestOptions(
- random_bytes(32), // Challenge
- 60000, // Timeout
- $this->stripPort($serverHost), // Relying Party ID
- $registeredPublicKeyCredentialDescriptors, // Registered PublicKeyCredentialDescriptor classes
- AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_DISCOURAGED
+ random_bytes(32), // Challenge
+ $this->stripPort($serverHost), // Relying Party ID
+ $registeredPublicKeyCredentialDescriptors, // Registered PublicKeyCredentialDescriptor classes
+ $userVerificationRequirement,
+ 60000, // Timeout
);
}
@@ -213,16 +201,15 @@ class Manager {
$tokenBindingHandler,
$extensionOutputCheckerHandler,
$algorithmManager,
- null,
- $this->logger,
);
+ $authenticatorAssertionResponseValidator->setLogger($this->logger);
try {
$this->logger->debug('Loading publickey credentials from: ' . $data);
// Load the data
$publicKeyCredential = $publicKeyCredentialLoader->load($data);
- $response = $publicKeyCredential->getResponse();
+ $response = $publicKeyCredential->response;
// Check if the response is an Authenticator Attestation Response
if (!$response instanceof AuthenticatorAssertionResponse) {
@@ -233,18 +220,17 @@ class Manager {
$request = ServerRequest::fromGlobals();
$publicKeyCredentialSource = $authenticatorAssertionResponseValidator->check(
- $publicKeyCredential->getRawId(),
+ $publicKeyCredential->rawId,
$response,
$publicKeyCredentialRequestOptions,
$request,
- $uid
+ $uid,
+ ['localhost'],
);
} catch (\Throwable $e) {
throw $e;
}
-
-
return true;
}
@@ -260,14 +246,6 @@ class Manager {
}
public function isWebAuthnAvailable(): bool {
- if (!extension_loaded('bcmath')) {
- return false;
- }
-
- if (!extension_loaded('gmp')) {
- return false;
- }
-
if (!$this->config->getSystemValueBool('auth.webauthn.enabled', true)) {
return false;
}