From 5d5cc28062a3f10d866b92244d84313ee592dba8 Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Fri, 25 Jul 2025 12:42:38 +0200 Subject: [PATCH 1/2] only check oidc login token if logged in via user_oidc Signed-off-by: Julien Veyssier --- lib/Service/TokenService.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lib/Service/TokenService.php b/lib/Service/TokenService.php index 3c16efaa0..3aabe0779 100644 --- a/lib/Service/TokenService.php +++ b/lib/Service/TokenService.php @@ -10,6 +10,7 @@ use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Exception\ServerException; +use OC\Authentication\Token\IProvider; use OCA\UserOIDC\AppInfo\Application; use OCA\UserOIDC\Db\ProviderMapper; use OCA\UserOIDC\Exception\TokenExchangeFailedException; @@ -19,6 +20,10 @@ use OCP\App\IAppManager; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; +use OCP\Authentication\Exceptions\ExpiredTokenException; +use OCP\Authentication\Exceptions\InvalidTokenException; +use OCP\Authentication\Exceptions\WipeTokenException; +use OCP\Authentication\Token\IToken; use OCP\EventDispatcher\IEventDispatcher; use OCP\Http\Client\IClient; use OCP\IConfig; @@ -28,6 +33,7 @@ use OCP\IUserSession; use OCP\PreConditionNotMetException; use OCP\Security\ICrypto; +use OCP\Session\Exceptions\SessionNotAvailableException; use Psr\Log\LoggerInterface; /** @@ -45,6 +51,7 @@ public function __construct( public HttpClientHelper $clientService, private ISession $session, private IUserSession $userSession, + private IProvider $tokenProvider, private IConfig $config, private LoggerInterface $logger, private ICrypto $crypto, @@ -111,6 +118,7 @@ public function checkLoginToken(): void { if (!$storeLoginTokenEnabled) { return; } + $this->logger->debug('[TokenService] checkLoginToken: store_login_token is enabled'); $currentUser = $this->userSession->getUser(); if (!$this->userSession->isLoggedIn() || $currentUser === null) { @@ -122,6 +130,22 @@ public function checkLoginToken(): void { return; } + // Do not check the OIDC login token when not logged in via user_oidc (app password or direct login for example) + // Inspired from https://github.com/nextcloud/server/pull/43942/files#diff-c5cef03f925f97933ff9b3eb10217d21ef6516342e5628762756f1ba0469ac84R81-R92 + try { + $sessionId = $this->session->getId(); + $sessionAuthToken = $this->tokenProvider->getToken($sessionId); + } catch (SessionNotAvailableException|InvalidTokenException|WipeTokenException|ExpiredTokenException $e) { + // States we do not deal with here. + $this->logger->debug('[TokenService] checkLoginToken: error getting the session auth token', ['exception' => $e]); + return; + } + $scope = $sessionAuthToken->getScopeAsArray(); + if (!isset($scope[IToken::SCOPE_SKIP_PASSWORD_VALIDATION]) || $scope[IToken::SCOPE_SKIP_PASSWORD_VALIDATION] === false) { + $this->logger->debug('[TokenService] checkLoginToken: most likely not using user_oidc, the session auth token does not have the "skip pwd validation" scope'); + return; + } + $token = $this->getToken(); if ($token === null) { $this->logger->debug('[TokenService] checkLoginToken: token is null'); @@ -130,11 +154,14 @@ public function checkLoginToken(): void { // so we need to reauthenticate $this->logger->debug('[TokenService] checkLoginToken: token is null and user had_token_once -> logout'); $this->userSession->logout(); + return; } elseif ($token->isExpired()) { $this->logger->debug('[TokenService] checkLoginToken: token is still expired -> reauthenticate'); // if the token is not valid, it means we couldn't refresh it so we need to reauthenticate to get a fresh token $this->reauthenticate($token->getProviderId()); + return; } + $this->logger->debug('[TokenService] checkLoginToken: all good'); } public function reauthenticate(int $providerId) { From 3a37e5b68252fe5094b31530d89038ac94d7f1c5 Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Wed, 30 Jul 2025 15:05:55 +0200 Subject: [PATCH 2/2] fix psalm issue about IToken::SCOPE_SKIP_PASSWORD_VALIDATION only available since 30 Signed-off-by: Julien Veyssier --- lib/Service/TokenService.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/Service/TokenService.php b/lib/Service/TokenService.php index 3aabe0779..2fdc54d79 100644 --- a/lib/Service/TokenService.php +++ b/lib/Service/TokenService.php @@ -141,7 +141,12 @@ public function checkLoginToken(): void { return; } $scope = $sessionAuthToken->getScopeAsArray(); - if (!isset($scope[IToken::SCOPE_SKIP_PASSWORD_VALIDATION]) || $scope[IToken::SCOPE_SKIP_PASSWORD_VALIDATION] === false) { + if (defined(IToken::class . '::SCOPE_SKIP_PASSWORD_VALIDATION') + && ( + !isset($scope[IToken::SCOPE_SKIP_PASSWORD_VALIDATION]) + || $scope[IToken::SCOPE_SKIP_PASSWORD_VALIDATION] === false + ) + ) { $this->logger->debug('[TokenService] checkLoginToken: most likely not using user_oidc, the session auth token does not have the "skip pwd validation" scope'); return; }