fix(auth): Session-Wiederherstellung nicht an active_userid koppeln

Trennt hasUnlockedLocalCrypto (Master-Key + Username) von
hasUnlockedLocalSession (+ userId für API), damit ein gültiges
Server-Cookie ohne userId in der Antwort keinen fälschlichen Logout auslöst.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-31 11:35:17 +02:00
co-authored by Cursor
parent 15f2172a38
commit 72cbad8d5e
3 changed files with 49 additions and 11 deletions
+7 -6
View File
@@ -46,13 +46,14 @@ export async function checkServerSession(): Promise<{ authenticated: boolean; us
}
}
/** Master key is memory-only; after process kill the HTTP session may outlive local crypto state. */
/** Master key + username in memory/storage — enough to stay in the unlocked UI. */
export function hasUnlockedLocalCrypto(): boolean {
return !!(getActiveMasterKey() && localStorage.getItem('active_username'))
}
/** Crypto unlock plus user id for authenticated API calls (userId may already be in localStorage). */
export function hasUnlockedLocalSession(): boolean {
return !!(
getActiveMasterKey() &&
localStorage.getItem('active_username') &&
localStorage.getItem('active_userid')
)
return hasUnlockedLocalCrypto() && !!localStorage.getItem('active_userid')
}
export async function reauthWithPasskey(): Promise<boolean> {
+34
View File
@@ -0,0 +1,34 @@
import { beforeEach, describe, expect, it } from 'vitest'
import {
hasUnlockedLocalCrypto,
hasUnlockedLocalSession,
setActiveMasterKey
} from './auth.js'
describe('local session unlock checks', () => {
beforeEach(() => {
localStorage.clear()
setActiveMasterKey(null)
})
it('hasUnlockedLocalCrypto with master key and username only', () => {
setActiveMasterKey(new ArrayBuffer(32))
localStorage.setItem('active_username', 'skipper')
expect(hasUnlockedLocalCrypto()).toBe(true)
expect(hasUnlockedLocalSession()).toBe(false)
})
it('hasUnlockedLocalSession when userId is present', () => {
setActiveMasterKey(new ArrayBuffer(32))
localStorage.setItem('active_username', 'skipper')
localStorage.setItem('active_userid', 'user-1')
expect(hasUnlockedLocalCrypto()).toBe(true)
expect(hasUnlockedLocalSession()).toBe(true)
})
it('hasUnlockedLocalCrypto false without master key', () => {
localStorage.setItem('active_username', 'skipper')
localStorage.setItem('active_userid', 'user-1')
expect(hasUnlockedLocalCrypto()).toBe(false)
})
})