fix: session_expired after login on HTTP deployments (#241)

Three changes to fix the immediate-logout issue reported by multiple
Docker users:

1. Add explicit `credentials: 'same-origin'` to the login fetch call.
   This was the only fetch in the entire codebase missing it. While
   modern browsers default to 'same-origin', some privacy configs or
   older engines may default to 'omit', silently dropping Set-Cookie
   headers from the login response.

2. Post-login cookie verification: after a successful login, the
   frontend now checks that the CSRF cookie (non-HttpOnly, readable
   by JS) was actually stored before redirecting. If the browser
   rejected the cookies, a clear error message is shown explaining
   the OXICLOUD_COOKIE_SECURE / HTTP mismatch.

3. Server-side diagnostic: the login handler now warns in logs when
   Secure cookies are set on a request that didn't arrive via HTTPS
   (no X-Forwarded-Proto: https header), pointing admins to the
   OXICLOUD_COOKIE_SECURE=false fix.

Root cause: users who set OXICLOUD_BASE_URL=https://... (or have
OXICLOUD_COOKIE_SECURE=true) but access via plain HTTP get cookies
with the Secure flag, which browsers silently reject over HTTP.
This commit is contained in:
Diocrafts
2026-04-12 01:38:19 +02:00
parent 5be035a172
commit c512534bfa
3 changed files with 40 additions and 1 deletions
+16 -1
View File
@@ -898,7 +898,21 @@ if (isLoginPage && loginForm) {
localStorage.setItem(USER_DATA_KEY, JSON.stringify(data.user));
}
// Redirect to main app
// Redirect to main app — but first verify the browser accepted
// the auth cookies. The CSRF cookie (oxicloud_csrf) is non-HttpOnly
// so JS can read it. If it's missing the browser rejected the
// Set-Cookie (usually because of Secure flag over plain HTTP).
const csrfStored = document.cookie.split('; ').some(c => c.startsWith('oxicloud_csrf='));
if (!csrfStored) {
console.error('Auth cookies were NOT stored by the browser. '
+ 'This usually means OXICLOUD_COOKIE_SECURE=true (or OXICLOUD_BASE_URL=https://...) '
+ 'is set but you are accessing via plain HTTP.');
loginError.textContent = 'Login succeeded but the browser rejected the session cookie. '
+ 'If you are accessing via HTTP, set OXICLOUD_COOKIE_SECURE=false in your .env file '
+ 'or access via HTTPS through a reverse proxy.';
loginError.style.display = 'block';
return;
}
redirectToMainApp();
} catch (error) {
loginError.textContent = error.message || 'Error logging in';
@@ -1030,6 +1044,7 @@ async function login(username, password) {
const response = await fetch(LOGIN_ENDPOINT, {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
...getCsrfHeaders()