Skip to content

Commit 71f1f87

Browse files
committed
chore(cypress): Try to analyze failures on login
Assisted-by: ClaudeCode:claude-fable-5 Signed-off-by: David Dreschner <david.dreschner@nextcloud.com>
1 parent 1e15be9 commit 71f1f87

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

core/Controller/CSRFTokenController.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,23 @@ public function index(): JSONResponse {
5656

5757
$requestToken = $this->tokenManager->getToken();
5858

59+
// [login-diag] Record the session this token was issued into, so a later
60+
// csrfCheckFailed on /login can be matched against it: if the /login
61+
// session/sessCookie differs from what /csrftoken issued into, the token
62+
// legitimately isn't in /login's session (a session-mismatch race).
63+
try {
64+
$session = \OCP\Server::get(\OCP\ISession::class);
65+
$raw = $this->request->getCookie(session_name());
66+
\OCP\Server::get(\Psr\Log\LoggerInterface::class)->error(
67+
'[login-diag] CSRFTOKEN issued remote=' . $this->request->getRemoteAddress()
68+
. ' session=' . substr(md5((string)$session->getId()), 0, 8)
69+
. ' sessCookie=' . ($raw !== null ? substr(md5($raw), 0, 8) : 'none'),
70+
['app' => 'login-diag'],
71+
);
72+
} catch (\Throwable) {
73+
// diagnostics must never affect the token endpoint
74+
}
75+
5976
return new JSONResponse([
6077
'token' => $requestToken->getEncryptedValue(),
6178
]);

core/Controller/LoginController.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,39 @@ private function logLoginDiag(string $what, string $user): void {
391391
} catch (\Throwable) {
392392
$session = 'n/a';
393393
}
394+
// Break down passesCSRFCheck() so a csrfCheckFailed tells us WHICH
395+
// sub-check failed: the strict same-site cookie check, or the token
396+
// validation (a missing session 'requesttoken' means the /login
397+
// request landed on a different session than /csrftoken issued into).
398+
try {
399+
$strictCookie = $this->request->passesStrictCookieCheck() ? '1' : '0';
400+
} catch (\Throwable) {
401+
$strictCookie = 'err';
402+
}
403+
try {
404+
$sessHasReqToken = $this->session->exists('requesttoken') ? '1' : '0';
405+
} catch (\Throwable) {
406+
$sessHasReqToken = 'err';
407+
}
408+
// Hash of the session cookie the client actually sent, to compare the
409+
// /csrftoken-issuing session against the /login session.
410+
$sessCookie = 'none';
411+
try {
412+
$raw = $this->request->getCookie(session_name());
413+
if ($raw !== null) {
414+
$sessCookie = substr(md5($raw), 0, 8);
415+
}
416+
} catch (\Throwable) {
417+
$sessCookie = 'err';
418+
}
394419
\OCP\Server::get(\Psr\Log\LoggerInterface::class)->error(
395420
'[login-diag] ' . $what
396421
. ' user=' . $user
397422
. ' remote=' . $remote
398423
. ' session=' . $session
424+
. ' sessCookie=' . $sessCookie
425+
. ' strictCookie=' . $strictCookie
426+
. ' sessHasReqToken=' . $sessHasReqToken
399427
. ' csrf=' . ($this->request->passesCSRFCheck() ? '1' : '0')
400428
. ' origin=' . $this->request->getHeader('Origin')
401429
. ' delay=' . $this->throttler->getDelay($remote, 'login'),

0 commit comments

Comments
 (0)