Selbstheilung: /api/auth/me stellt abgelaufenes/fehlendes preview_session-Cookie neu aus

Portal-Session (webklar_portal_session) lebt unabhaengig vom preview_session-JWT.
Fehlte das Preview-Cookie (WebView-Datenverlust, Ablauf), liefen alle
*.project.webklar.com-Hosts in eine 302-Login-Schleife (schwarze Seite im
Kundenportal), obwohl der Nutzer eingeloggt war - Re-Login war der einzige
Ausweg. Jetzt heilt jeder Aufruf der Projektuebersicht das Cookie automatisch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-07-22 20:13:44 +00:00
parent 55991c9008
commit a4b4974431

View File

@@ -297,6 +297,22 @@ router.get('/staff-preview', async (req, res) => {
return res.redirect(previewUrl) return res.redirect(previewUrl)
}) })
// Selbstheilung: Portal-Session lebt oft laenger als das preview_session-Cookie
// (bzw. das Cookie fehlt nach WebView-/Browser-Datenverlust). Ohne gueltiges
// Preview-Cookie laufen die *.project.webklar.com-Hosts in eine 302-Schleife.
// Deshalb stellt /me das Preview-Cookie automatisch neu aus, solange die
// Portal-Session gueltig ist.
async function refreshPreviewCookie(req, res, payload) {
try {
const existing = req.cookies?.[PREVIEW_COOKIE_NAME]
if (existing && (await verifyPreviewSessionToken(existing))) return
const token = await createPreviewSessionToken(payload)
res.cookie(PREVIEW_COOKIE_NAME, token, previewSessionCookieOptions())
} catch (err) {
console.warn('[auth] preview-cookie refresh failed:', err.message)
}
}
router.get('/me', async (req, res) => { router.get('/me', async (req, res) => {
const raw = req.signedCookies?.[config.cookieName] const raw = req.signedCookies?.[config.cookieName]
if (!raw) { if (!raw) {
@@ -313,6 +329,15 @@ router.get('/me', async (req, res) => {
const doc = await getDocument(config.collections.customers, session.customerId).catch(() => null) const doc = await getDocument(config.collections.customers, session.customerId).catch(() => null)
if (doc) customer = sanitizeCustomer(doc) if (doc) customer = sanitizeCustomer(doc)
} }
await refreshPreviewCookie(req, res, {
userId: session.appwriteUserId,
customerId: '',
email: session.adminEmail || session.email || '',
name: session.adminName || session.name || 'Admin',
role: 'admin',
labels: ['admin'],
authSource: 'kundenbereich-admin',
})
return res.json({ return res.json({
authenticated: true, authenticated: true,
role: 'admin', role: 'admin',
@@ -348,6 +373,16 @@ router.get('/me', async (req, res) => {
customer = await syncCustomerAppwriteUserId(customer, session.appwriteUserId) customer = await syncCustomerAppwriteUserId(customer, session.appwriteUserId)
} }
await refreshPreviewCookie(req, res, {
userId: session.appwriteUserId,
customerId: customer.$id,
email: customer.email || session.email || '',
name: customer.name || session.name || '',
role: 'customer',
labels: [],
authSource: 'kundenbereich',
})
return res.json({ return res.json({
authenticated: true, authenticated: true,
role: 'customer', role: 'customer',