From aa73b78f6f66ef8fb1af77df243d0b91d23dd913 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Thu, 20 Aug 2026 10:28:08 +0200 Subject: [PATCH 1/4] feat: Add more debug output when checkTokenCredentials fails Signed-off-by: Carl Schwan --- lib/private/User/Session.php | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index 95d839c173d42..7fbfbb72e9c15 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -696,7 +696,7 @@ private function getPassword($password) { * @param string $token * @return boolean */ - private function checkTokenCredentials(IToken $dbToken, $token) { + private function checkTokenCredentials(IToken $dbToken, $token, array &$reason) { // Check whether login credentials are still valid and the user was not disabled // This check is performed each 5 minutes $lastCheck = $dbToken->getLastCheck() ? : 0; @@ -709,12 +709,19 @@ private function checkTokenCredentials(IToken $dbToken, $token) { try { $pwd = $this->tokenProvider->getPassword($dbToken, $token); } catch (InvalidTokenException $ex) { + $reason = [ + 'exception' => $ex, + ]; + // An invalid token password was used -> log user out return false; } catch (PasswordlessTokenException $ex) { // Token has no password - if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) { + $reason = [ + 'exception' => $ex, + 'message' => 'Paswordless token exception with no active or disabled user', + ]; $this->tokenProvider->invalidateToken($token); return false; } @@ -725,12 +732,18 @@ private function checkTokenCredentials(IToken $dbToken, $token) { // Invalidate token if the user is no longer active if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) { $this->tokenProvider->invalidateToken($token); + $reason = [ + 'message' => 'Invalidate token as the user is no longer active', + ]; return false; } // If the token password is no longer valid mark it as such if ($this->manager->checkPassword($dbToken->getLoginName(), $pwd) === false) { $this->tokenProvider->markPasswordInvalid($dbToken, $token); + $reason = [ + 'message' => 'The token password is no longer valid', + ]; // User is logged out return false; } @@ -768,11 +781,12 @@ private function validateToken($token, $user = null) { return false; } - if (!$this->checkTokenCredentials($dbToken, $token)) { - $this->logger->warning('Session token credentials are invalid', [ + $reason = []; + if (!$this->checkTokenCredentials($dbToken, $token, $reason)) { + $this->logger->warning('Session token credentials are invalid', array_merge($reason, [ 'app' => 'core', 'user' => $user, - ]); + ])); return false; } From 8593595b0e1ccf6cf257a63962d8ff3b577a571c Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Thu, 20 Aug 2026 10:44:32 +0200 Subject: [PATCH 2/4] fix: Add backtrace when login fails Signed-off-by: Carl Schwan --- lib/private/User/Session.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index 7fbfbb72e9c15..50af38cb164e1 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -464,7 +464,7 @@ public function logClientIn($user, } private function handleLoginFailed(IThrottler $throttler, int $currentDelay, string $remoteAddress, string $user, ?string $password) { - $this->logger->warning("Login failed: '" . $user . "' (Remote IP: '" . $remoteAddress . "')", ['app' => 'core']); + $this->logger->warning("Login failed: '" . $user . "' (Remote IP: '" . $remoteAddress . "')", ['app' => 'core', 'exception' => new \Exception()]); $throttler->registerAttempt('login', $remoteAddress, ['user' => $user]); $this->dispatcher->dispatchTyped(new LoginFailed($user, $password)); @@ -761,11 +761,9 @@ private function checkTokenCredentials(IToken $dbToken, $token, array &$reason) * * Invalidates the token if checks fail * - * @param string $token - * @param string $user login name - * @return boolean + * @param ?string $user The login name */ - private function validateToken($token, $user = null) { + private function validateToken(string $token, ?string $user = null): bool { try { $dbToken = $this->tokenProvider->getToken($token); } catch (InvalidTokenException $ex) { From f1c7f88cb1887851d0a4316b4fcbaf318605c4d2 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Thu, 20 Aug 2026 11:40:43 +0200 Subject: [PATCH 3/4] chore: Add more debug output Signed-off-by: Carl Schwan --- .../Authentication/Token/PublicKeyToken.php | 6 +++++- lib/private/User/Session.php | 14 ++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/private/Authentication/Token/PublicKeyToken.php b/lib/private/Authentication/Token/PublicKeyToken.php index 11739507851e1..ebd919b09adda 100644 --- a/lib/private/Authentication/Token/PublicKeyToken.php +++ b/lib/private/Authentication/Token/PublicKeyToken.php @@ -127,7 +127,11 @@ public function getLoginName(): string { */ #[\Override] public function getPassword(): ?string { - return parent::getPassword(); + $password = parent::getPassword(); + if ($password === '') { + return null; + } + return $password; } #[\Override] diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index 50af38cb164e1..519ac7456db43 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -464,7 +464,7 @@ public function logClientIn($user, } private function handleLoginFailed(IThrottler $throttler, int $currentDelay, string $remoteAddress, string $user, ?string $password) { - $this->logger->warning("Login failed: '" . $user . "' (Remote IP: '" . $remoteAddress . "')", ['app' => 'core', 'exception' => new \Exception()]); + $this->logger->debug("Login failed: '" . $user . "' (Remote IP: '" . $remoteAddress . "')", ['app' => 'core', 'exception' => new \Exception()]); $throttler->registerAttempt('login', $remoteAddress, ['user' => $user]); $this->dispatcher->dispatchTyped(new LoginFailed($user, $password)); @@ -720,7 +720,7 @@ private function checkTokenCredentials(IToken $dbToken, $token, array &$reason) if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) { $reason = [ 'exception' => $ex, - 'message' => 'Paswordless token exception with no active or disabled user', + 'additional_message' => 'Passwordless token exception with no active or disabled user', ]; $this->tokenProvider->invalidateToken($token); return false; @@ -733,7 +733,7 @@ private function checkTokenCredentials(IToken $dbToken, $token, array &$reason) if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) { $this->tokenProvider->invalidateToken($token); $reason = [ - 'message' => 'Invalidate token as the user is no longer active', + 'additional_message' => 'Invalidate token as the user is no longer active', ]; return false; } @@ -742,7 +742,7 @@ private function checkTokenCredentials(IToken $dbToken, $token, array &$reason) if ($this->manager->checkPassword($dbToken->getLoginName(), $pwd) === false) { $this->tokenProvider->markPasswordInvalid($dbToken, $token); $reason = [ - 'message' => 'The token password is no longer valid', + 'additional_message' => 'The token password is no longer valid and is ' . (empty($pwd) ? 'empty' : 'not empty'), ]; // User is logged out return false; @@ -781,10 +781,12 @@ private function validateToken(string $token, ?string $user = null): bool { $reason = []; if (!$this->checkTokenCredentials($dbToken, $token, $reason)) { - $this->logger->warning('Session token credentials are invalid', array_merge($reason, [ + $this->logger->warning('Session token credentials are invalid', [ 'app' => 'core', 'user' => $user, - ])); + 'token name' => $dbToken->getName(), + ...$reason, + ]); return false; } From 1f9668a2ca9ba0375e074a399d7e3573b629920f Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Wed, 9 Sep 2026 15:22:38 +0200 Subject: [PATCH 4/4] fix(ldap): Display agent name when bind fails Signed-off-by: Carl Schwan --- apps/user_ldap/lib/Connection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php index 367c79d7e5d95..1550505d868a8 100644 --- a/apps/user_ldap/lib/Connection.php +++ b/apps/user_ldap/lib/Connection.php @@ -748,7 +748,7 @@ public function bind() { $errno = $this->ldap->errno($cr); $this->logger->warning( - 'Bind failed: ' . $errno . ': ' . $this->ldap->error($cr), + 'Bind failed for ' . $this->configuration->ldapAgentName . ': ' . $errno . ': ' . $this->ldap->error($cr), ['app' => 'user_ldap'] );