Skip to content

fix: don't set session user in getCurrentUserId - #1486

Open
mosi-kha wants to merge 1 commit into
nextcloud:mainfrom
mosi-kha:fix/1452-bearer-session-token
Open

fix: don't set session user in getCurrentUserId#1486
mosi-kha wants to merge 1 commit into
nextcloud:mainfrom
mosi-kha:fix/1452-bearer-session-token

Conversation

@mosi-kha

@mosi-kha mosi-kha commented Aug 6, 2026

Copy link
Copy Markdown

Fixes #1452

Problem

setSessionUser(), added in #1376, is called from the first line of getCurrentUserId(). loginWithApache() guards its whole login block on the active user not already being set:

$uid = $backend->getCurrentUserId();
if ($uid) {
    if (self::getUser() !== $uid) {     // <- guard
        ...
        $userSession->createSessionToken($request, $uid, $uid, $password);
        $userSession->createRememberMeToken($userSession->getUser());
        // token scopes, setupFS, post_login hook, UserLoggedInEvent
    }
    return true;
}

IUserSession::setUser() persists user_id into the session, so by the time control reaches the guard it's already satisfied and the entire block is skipped. No oc_authtoken row is ever created for that session.

Impact

Not just app passwords (#1452's original symptom). Session::validateSession() looks up a token by session id on every request that reuses the session cookie; with no row to find, it calls logout(), which strips the cookie. A client that authenticates once with a bearer token and relies on the cookie for follow-up requests gets a 401 on the very next request.

Confirmed independently on master and 8.11.0-dev: bearer request then cookie-only request goes 200401 with the calls in place, 200200 with them removed.

DAV also reaches this code, through its own handleApacheAuth() call site in apps/dav/lib/Connector/Sabre/Auth.php, separate from OC::handleLogin(). Confirmed 207 both before and after this change.

Why a revert

getCurrentUserId() is called before loginWithApache()'s guard, and there's no hook in between — nothing the app does inside getCurrentUserId() can both satisfy the guard and leave a token row behind, since satisfying the guard is what skips the code that creates the row. A "complete the login inside the app" approach was considered and dropped: it only works by keeping the guard closed on purpose, which means maintaining a parallel login path here that has to keep tracking core's.

The setupFS/keygen cost this avoided is real, but it's a separate, filed issue — after this revert, every bearer request without a session cookie re-pays it, same as before #1376.

Testing

composer lint && composer cs:check && composer psalm clean, no baseline changes.

No unit test added — tests/unit/ has no existing coverage of Backend.php, and this is only observable end-to-end (bearer request → cookie reuse), which needs a running server, not a unit fixture.

Reverts the setSessionUser() calls added in nextcloud#1376.

IApacheBackend::getCurrentUserId() is called from the first line of
loginWithApache(), which guards its whole login block on the active
user not already being set. Setting the session user inside
getCurrentUserId() satisfies that guard before core reaches it, so the
entire block gets skipped: no oc_authtoken row, no remember-me cookie,
no filesystem setup, no login events.

The missing token row breaks any later request that reuses the
session cookie. Session::validateSession() looks up a token by session
id, finds none, and calls logout(), which strips the cookie and
returns a 401.

Confirmed independently against master and 8.11.0-dev: bearer request
then cookie-only request goes 200 then 401 with the calls in place,
200 then 200 with them removed. DAV also reaches this code through
apps/dav's own handleApacheAuth() call site, confirmed 207 both before
and after.

Signed-off-by: mostafa <mostafakhaki00@gmail.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] setSessionUser() in getCurrentUserId() breaks loginWithExternalBackend() — no oc_authtoken created, AppPasswordController returns 403

1 participant