From bd59243e2ccbda7bf4d08a485a88ae55daaf7643 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 22 May 2026 22:16:31 +0000 Subject: [PATCH] Fix Login: Appwrite-Session ohne secret auf dem Server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit session.secret wird ohne API-Key nicht zurückgegeben. Login nutzt daher session.userId und die Admin Users API statt account.get(). Co-authored-by: Cursor --- server/routes/auth.js | 26 -------------- server/services/appwriteAdmin.js | 3 +- server/services/appwriteClient.js | 60 +++++++++---------------------- 3 files changed, 19 insertions(+), 70 deletions(-) diff --git a/server/routes/auth.js b/server/routes/auth.js index aef0ce4..86c872b 100644 --- a/server/routes/auth.js +++ b/server/routes/auth.js @@ -59,23 +59,6 @@ async function validatePortalAccess(appwriteUserId) { return { customer, portalAccess } } -const DEBUG_LOG = (location, message, data, hypothesisId) => { - // #region agent log - fetch('http://127.0.0.1:7281/ingest/30e8e71c-b377-4e72-84f9-593826c6d234', { - method: 'POST', - headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': '80bbfc' }, - body: JSON.stringify({ - sessionId: '80bbfc', - location, - message, - data, - hypothesisId, - timestamp: Date.now(), - }), - }).catch(() => {}) - // #endregion -} - router.post('/login', async (req, res) => { const { email, password } = req.body || {} if (!email || !password) { @@ -84,12 +67,7 @@ router.post('/login', async (req, res) => { try { const user = await loginWithAppwrite(email.trim(), password) - DEBUG_LOG('auth.js:login', 'appwrite user ok', { userId: user.$id }, 'H3') const { customer, portalAccess } = await validatePortalAccess(user.$id) - DEBUG_LOG('auth.js:login', 'portal validation ok', { - customerId: customer.$id, - portalAccessEnabled: Boolean(customer.portalAccessEnabled), - }, 'H4') setPortalSession(res, { customerId: customer.$id, @@ -109,10 +87,6 @@ router.post('/login', async (req, res) => { return res.json({ success: true, customer: sanitizeCustomer(customer) }) } catch (err) { const status = err.status || 500 - DEBUG_LOG('auth.js:login', 'login failed', { - status, - message: err?.message?.slice(0, 120), - }, status === 403 ? 'H4' : status === 401 ? 'H1' : 'H5') return res.status(status).json({ error: err.message || 'Anmeldung fehlgeschlagen' }) } }) diff --git a/server/services/appwriteAdmin.js b/server/services/appwriteAdmin.js index 14bee2d..ba4c8c5 100644 --- a/server/services/appwriteAdmin.js +++ b/server/services/appwriteAdmin.js @@ -1,4 +1,4 @@ -import { Client, Account, Databases, ID, Query } from 'node-appwrite' +import { Client, Account, Databases, ID, Query, Users } from 'node-appwrite' import { config } from '../config.js' export function createAdminClient() { @@ -10,6 +10,7 @@ export function createAdminClient() { return { client, databases: new Databases(client), + users: new Users(client), } } diff --git a/server/services/appwriteClient.js b/server/services/appwriteClient.js index c68df74..4dc0acb 100644 --- a/server/services/appwriteClient.js +++ b/server/services/appwriteClient.js @@ -1,70 +1,44 @@ -import { createUserClient } from './appwriteAdmin.js' - -const DEBUG_LOG = (location, message, data, hypothesisId) => { - // #region agent log - fetch('http://127.0.0.1:7281/ingest/30e8e71c-b377-4e72-84f9-593826c6d234', { - method: 'POST', - headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': '80bbfc' }, - body: JSON.stringify({ - sessionId: '80bbfc', - location, - message, - data, - hypothesisId, - timestamp: Date.now(), - }), - }).catch(() => {}) - // #endregion -} +import { createUserClient, createAdminClient } from './appwriteAdmin.js' +/** + * Appwrite liefert session.secret nur bei Requests mit API-Key. + * Server-seitiger E-Mail-Login nutzt daher userId aus der Session + Admin Users API. + */ export async function loginWithAppwrite(email, password) { - const { client, account } = createUserClient() + const { account } = createUserClient() let session try { session = await account.createEmailPasswordSession(email, password) - DEBUG_LOG('appwriteClient.js:session', 'createEmailPasswordSession ok', { - hasSecret: Boolean(session?.secret), - sessionId: session?.$id || null, - }, 'H1') } catch (err) { - DEBUG_LOG('appwriteClient.js:session', 'createEmailPasswordSession fail', { - code: err?.code, - type: err?.type, - message: err?.message?.slice(0, 120), - }, 'H1') const message = err?.message || 'Anmeldung fehlgeschlagen' const error = new Error(message) error.status = 401 throw error } - if (session?.secret) { - client.setSession(session.secret) - DEBUG_LOG('appwriteClient.js:setSession', 'setSession applied', { hasSessionHeader: true }, 'H2') - } else { - DEBUG_LOG('appwriteClient.js:setSession', 'no session.secret', {}, 'H2') + const userId = session?.userId + if (!userId) { + const error = new Error('Appwrite-Session ohne Benutzer-ID') + error.status = 500 + throw error } + const { users } = createAdminClient() let user try { - user = await account.get() - DEBUG_LOG('appwriteClient.js:get', 'account.get ok', { userId: user?.$id || null }, 'H2') + user = await users.get(userId) } catch (err) { - DEBUG_LOG('appwriteClient.js:get', 'account.get fail', { - code: err?.code, - message: err?.message?.slice(0, 120), - }, 'H2') - const message = err?.message || 'Anmeldung fehlgeschlagen' + const message = err?.message || 'Benutzer konnte nicht geladen werden' const error = new Error(message) - error.status = err?.message?.includes('scopes') ? 401 : 500 + error.status = 500 throw error } try { - await account.deleteSession('current') + await users.deleteSession(userId, session.$id) } catch { - // Portal nutzt eigene Session; Appwrite-Session wird nicht persistiert + // Portal nutzt eigene Cookie-Session; Appwrite-Session wird nicht persistiert } return user