aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php
diff options
context:
space:
mode:
authorArthur Schiwon <blizzz@arthur-schiwon.de>2024-03-01 18:37:47 +0100
committerArthur Schiwon <blizzz@arthur-schiwon.de>2024-06-05 19:01:13 +0200
commit340939e688fab5c52061bc9e358587fbd8ec9fc8 (patch)
tree8f26c43cfdb8be01684fec40fdabf3b10e000a76 /lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php
parent31b0a44cf65b6625636ea0fa15fb1a1122b525e1 (diff)
downloadnextcloud-server-340939e688fab5c52061bc9e358587fbd8ec9fc8.tar.gz
nextcloud-server-340939e688fab5c52061bc9e358587fbd8ec9fc8.zip
fix(Session): avoid password confirmation on SSO
SSO backends like SAML and OIDC tried a trick to suppress password confirmations as they are not possible by design. At least for SAML it was not reliable when existing user backends where used as user repositories. Now we are setting a special scope with the token, and also make sure that the scope is taken over when tokens are regenerated. Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
Diffstat (limited to 'lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php')
-rw-r--r--lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php26
1 files changed, 24 insertions, 2 deletions
diff --git a/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php b/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php
index b95a69dc3e2..9fa4aedd401 100644
--- a/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php
@@ -7,12 +7,17 @@ namespace OC\AppFramework\Middleware\Security;
use OC\AppFramework\Middleware\Security\Exceptions\NotConfirmedException;
use OC\AppFramework\Utility\ControllerMethodReflector;
+use OC\Authentication\Token\IProvider;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
use OCP\AppFramework\Middleware;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Authentication\Exceptions\ExpiredTokenException;
+use OCP\Authentication\Exceptions\InvalidTokenException;
+use OCP\Authentication\Exceptions\WipeTokenException;
use OCP\ISession;
use OCP\IUserSession;
+use OCP\Session\Exceptions\SessionNotAvailableException;
use OCP\User\Backend\IPasswordConfirmationBackend;
use ReflectionMethod;
@@ -27,6 +32,7 @@ class PasswordConfirmationMiddleware extends Middleware {
private $timeFactory;
/** @var array */
private $excludedUserBackEnds = ['user_saml' => true, 'user_globalsiteselector' => true];
+ private IProvider $tokenProvider;
/**
* PasswordConfirmationMiddleware constructor.
@@ -39,11 +45,14 @@ class PasswordConfirmationMiddleware extends Middleware {
public function __construct(ControllerMethodReflector $reflector,
ISession $session,
IUserSession $userSession,
- ITimeFactory $timeFactory) {
+ ITimeFactory $timeFactory,
+ IProvider $tokenProvider,
+ ) {
$this->reflector = $reflector;
$this->session = $session;
$this->userSession = $userSession;
$this->timeFactory = $timeFactory;
+ $this->tokenProvider = $tokenProvider;
}
/**
@@ -68,8 +77,21 @@ class PasswordConfirmationMiddleware extends Middleware {
$backendClassName = $user->getBackendClassName();
}
+ try {
+ $sessionId = $this->session->getId();
+ $token = $this->tokenProvider->getToken($sessionId);
+ } catch (SessionNotAvailableException|InvalidTokenException|WipeTokenException|ExpiredTokenException) {
+ // States we do not deal with here.
+ return;
+ }
+ $scope = $token->getScopeAsArray();
+ if (isset($scope['sso-based-login']) && $scope['sso-based-login'] === true) {
+ // Users logging in from SSO backends cannot confirm their password by design
+ return;
+ }
+
$lastConfirm = (int) $this->session->get('last-password-confirm');
- // we can't check the password against a SAML backend, so skip password confirmation in this case
+ // TODO: confirm excludedUserBackEnds can go away and remove it
if (!isset($this->excludedUserBackEnds[$backendClassName]) && $lastConfirm < ($this->timeFactory->getTime() - (30 * 60 + 15))) { // allow 15 seconds delay
throw new NotConfirmedException();
}