From 73e768a0ad91471714bfb0004c20acf5ed7d357b Mon Sep 17 00:00:00 2001 From: Linus Waldowsky Date: Mon, 9 Feb 2026 20:02:05 +0100 Subject: [PATCH] refactor: remove all JWT-related code and references JWT was never used - auth uses X-User-Id header. Removes jwt.ts utility, jsonwebtoken dependency, stubbed refresh/logout endpoints, and updates all docs (PUML diagrams, api-routes, tex, CLAUDE.md) accordingly. --- CLAUDE.md | 13 +-- apps/server/package.json | 2 - apps/server/src/controllers/AuthController.ts | 7 -- apps/server/src/routes/auth.routes.ts | 2 - apps/server/src/services/AuthService.ts | 10 +- apps/server/src/utils/index.ts | 1 - apps/server/src/utils/jwt.ts | 26 ----- docs/api-routes.md | 6 +- docs/architecture-class-diagram.puml | 8 -- docs/component-diagram.puml | 3 - docs/technisches_brainstorm.tex | 9 +- package-lock.json | 102 ------------------ 12 files changed, 10 insertions(+), 179 deletions(-) delete mode 100644 apps/server/src/utils/jwt.ts diff --git a/CLAUDE.md b/CLAUDE.md index c3419f6..7c233f3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,7 +48,7 @@ npm run start -w @calchat/server # Run compiled server (port 3000) | | MongoDB | Database | | | Mongoose | ODM | | | GPT (OpenAI) | AI/LLM for chat | -| | X-User-Id Header | Authentication (simple, no JWT yet) | +| | X-User-Id Header | Authentication | | | pino / pino-http | Structured logging | | | react-native-logs | Client-side logging | | | tsdav | CalDAV client library | @@ -235,7 +235,7 @@ CardBase src/ ├── app.ts # Entry point, DI setup, Express config ├── controllers/ # Request handlers + middleware (per architecture diagram) -│ ├── AuthController.ts # login(), register(), refresh(), logout() +│ ├── AuthController.ts # login(), register() │ ├── ChatController.ts # sendMessage(), confirmEvent() + CalDAV push, rejectEvent(), getConversations(), getConversation(), updateProposalEvent() │ ├── EventController.ts # create(), getById(), getAll(), getByDateRange(), update(), delete() - pushes/deletes to CalDAV on mutations │ ├── CaldavController.ts # saveConfig(), loadConfig(), deleteConfig(), pullEvents(), pushEvents(), pushEvent() @@ -285,7 +285,6 @@ src/ │ ├── toolDefinitions.ts # TOOL_DEFINITIONS - provider-agnostic tool specs │ └── toolExecutor.ts # executeToolCall() - handles getDay, proposeCreate/Update/Delete, searchEvents, getEventsInRange ├── utils/ -│ ├── jwt.ts # signToken(), verifyToken() - NOT USED YET (no JWT) │ ├── password.ts # hash(), compare() using bcrypt │ ├── eventFormatters.ts # getWeeksOverview(), getMonthOverview() - formatted event listings │ └── recurrenceExpander.ts # expandRecurringEvents() - expand recurring events into occurrences @@ -296,8 +295,6 @@ src/ **API Endpoints:** - `POST /api/auth/login` - User login - `POST /api/auth/register` - User registration -- `POST /api/auth/refresh` - Refresh JWT token -- `POST /api/auth/logout` - User logout - `GET /api/events` - Get all events (protected) - `GET /api/events/range` - Get events by date range (protected) - `GET /api/events/:id` - Get single event (protected) @@ -536,8 +533,6 @@ docker compose up -d # Start Radicale CalDAV server ### Environment Variables Server requires `.env` file in `apps/server/`: ``` -JWT_SECRET=your-secret-key -JWT_EXPIRES_IN=1h MONGODB_URI=mongodb://root:mongoose@localhost:27017/calchat?authSource=admin OPENAI_API_KEY=sk-proj-... USE_TEST_RESPONSES=false # true = static test responses, false = real GPT AI @@ -585,10 +580,6 @@ NODE_ENV=development # development = pretty logs, production = JSON - `EventService`: Extended with searchByTitle(), findByCaldavUUID() - `utils/eventFormatters`: Refactored to use EventService instead of EventRepository - CORS configured to allow X-User-Id header -- **Stubbed (TODO):** - - `AuthController`: refresh(), logout() - - `AuthService`: refreshToken() - - JWT authentication (currently using simple X-User-Id header) **Shared:** - Types, DTOs, constants (Day, Month with German translations), ExpandedEvent type, CaldavConfig, CaldavSyncStatus defined and exported diff --git a/apps/server/package.json b/apps/server/package.json index 91d132e..13d5f1d 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -14,7 +14,6 @@ "dotenv": "^16.4.7", "express": "^5.2.1", "ical.js": "^2.2.1", - "jsonwebtoken": "^9.0.3", "mongoose": "^9.1.1", "openai": "^6.15.0", "pino": "^10.1.1", @@ -27,7 +26,6 @@ "@types/express": "^5.0.6", "@types/ical": "^0.8.3", "@types/jest": "^30.0.0", - "@types/jsonwebtoken": "^9.0.10", "@types/node": "^24.10.1", "jest": "^30.2.0", "pino-pretty": "^13.1.3", diff --git a/apps/server/src/controllers/AuthController.ts b/apps/server/src/controllers/AuthController.ts index 46a186d..e1e9136 100644 --- a/apps/server/src/controllers/AuthController.ts +++ b/apps/server/src/controllers/AuthController.ts @@ -22,11 +22,4 @@ export class AuthController { } } - async refresh(req: Request, res: Response): Promise { - throw new Error("Not implemented"); - } - - async logout(req: Request, res: Response): Promise { - throw new Error("Not implemented"); - } } diff --git a/apps/server/src/routes/auth.routes.ts b/apps/server/src/routes/auth.routes.ts index caa047c..3cd03ce 100644 --- a/apps/server/src/routes/auth.routes.ts +++ b/apps/server/src/routes/auth.routes.ts @@ -6,8 +6,6 @@ export function createAuthRoutes(authController: AuthController): Router { router.post("/login", (req, res) => authController.login(req, res)); router.post("/register", (req, res) => authController.register(req, res)); - router.post("/refresh", (req, res) => authController.refresh(req, res)); - router.post("/logout", (req, res) => authController.logout(req, res)); return router; } diff --git a/apps/server/src/services/AuthService.ts b/apps/server/src/services/AuthService.ts index 968382e..0ef3c6d 100644 --- a/apps/server/src/services/AuthService.ts +++ b/apps/server/src/services/AuthService.ts @@ -1,6 +1,5 @@ -import { User, CreateUserDTO, LoginDTO, AuthResponse } from "@calchat/shared"; +import { CreateUserDTO, LoginDTO, AuthResponse } from "@calchat/shared"; import { UserRepository } from "./interfaces"; -import * as jwt from "../utils/jwt"; import * as password from "../utils/password"; export class AuthService { @@ -46,11 +45,4 @@ export class AuthService { return { user, accessToken: "" }; } - async refreshToken(refreshToken: string): Promise { - throw new Error("Not implemented"); - } - - async logout(userId: string): Promise { - throw new Error("Not implemented"); - } } diff --git a/apps/server/src/utils/index.ts b/apps/server/src/utils/index.ts index dab22a7..df7d49b 100644 --- a/apps/server/src/utils/index.ts +++ b/apps/server/src/utils/index.ts @@ -1,2 +1 @@ -export * from "./jwt"; export * from "./password"; diff --git a/apps/server/src/utils/jwt.ts b/apps/server/src/utils/jwt.ts deleted file mode 100644 index e496ff4..0000000 --- a/apps/server/src/utils/jwt.ts +++ /dev/null @@ -1,26 +0,0 @@ -import jwt from "jsonwebtoken"; - -export interface TokenPayload { - userId: string; - email: string; -} - -export interface JWTConfig { - secret: string; - expiresIn: string; -} - -const JWT_SECRET = process.env.JWT_SECRET || "your-secret-key"; -const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || "1h"; - -export function signToken(payload: TokenPayload): string { - throw new Error("Not implemented"); -} - -export function verifyToken(token: string): TokenPayload { - throw new Error("Not implemented"); -} - -export function decodeToken(token: string): TokenPayload | null { - throw new Error("Not implemented"); -} diff --git a/docs/api-routes.md b/docs/api-routes.md index ec5b39f..780b99b 100644 --- a/docs/api-routes.md +++ b/docs/api-routes.md @@ -11,15 +11,13 @@ Base URL: `/api` |--------|----------|--------------| | POST | `/auth/login` | User Login | | POST | `/auth/register` | User Registrierung | -| POST | `/auth/refresh` | JWT Token erneuern | -| POST | `/auth/logout` | User Logout | --- ## Events ### Event Endpoints (`/api/events`) -Alle Endpoints erfordern JWT-Authentifizierung. +Alle Endpoints erfordern Authentifizierung (X-User-Id Header). | Method | Endpoint | Beschreibung | |--------|----------|--------------| @@ -35,7 +33,7 @@ Alle Endpoints erfordern JWT-Authentifizierung. ## Chat ### Chat Endpoints (`/api/chat`) -Alle Endpoints erfordern JWT-Authentifizierung. +Alle Endpoints erfordern Authentifizierung (X-User-Id Header). | Method | Endpoint | Beschreibung | |--------|----------|--------------| diff --git a/docs/architecture-class-diagram.puml b/docs/architecture-class-diagram.puml index a08a147..898f27d 100644 --- a/docs/architecture-class-diagram.puml +++ b/docs/architecture-class-diagram.puml @@ -188,11 +188,6 @@ package "Models" #D3D3D3 { } package "Utils" #DDA0DD { - class JWT { - ' +signToken() - ' +verifyToken() - } - class Password { ' +hash() ' +compare() @@ -215,8 +210,6 @@ ChatController --> CaldavService EventController --> EventService EventController --> CaldavService CaldavController --> CaldavService -AuthMiddleware --> JWT - ' Service -> Interfaces (intern) AuthService --> UserRepository ChatService --> ChatRepository @@ -227,7 +220,6 @@ CaldavService --> CaldavRepository CaldavService --> EventService ' Auth uses Utils -AuthService --> JWT AuthService --> Password ' Event/Chat uses Utils diff --git a/docs/component-diagram.puml b/docs/component-diagram.puml index 6ca7cdb..c2bccc8 100644 --- a/docs/component-diagram.puml +++ b/docs/component-diagram.puml @@ -77,7 +77,6 @@ package "apps/server (Express.js)" as ServerPkg #98FB98 { } package "Utils" { - [JWT] as JWTUtil [Password] as PwdUtil [RecurrenceExpander] as RecExpander [EventFormatters] as EvtFormatters @@ -154,9 +153,7 @@ GPT ..|> Interfaces Repos ..|> Interfaces ' Backend: Service -> Utils -AuthSvc --> JWTUtil AuthSvc --> PwdUtil -Middleware --> JWTUtil EventSvc --> RecExpander ChatSvc --> EvtFormatters diff --git a/docs/technisches_brainstorm.tex b/docs/technisches_brainstorm.tex index 0d7266c..0fbb84d 100644 --- a/docs/technisches_brainstorm.tex +++ b/docs/technisches_brainstorm.tex @@ -66,7 +66,7 @@ Backend & Express.js & Web-App Framework \\ & MongoDB & Datenbank \\ & Mongoose & ODM \\ & Claude (Anthropic) & KI / LLM \\ - & JWT & Authentifizierung \\ + & X-User-Id Header & Authentifizierung \\ \hline Geplant & iCalendar & Event-Export \\ \hline @@ -112,8 +112,9 @@ Der wichtigste Teil der App ist die KI-Integration über \textbf{Claude} (Anthropic). Dieses LLM verarbeitet natürlichsprachliche Eingaben der Nutzer und generiert daraus strukturierte Event-Vorschläge. -Die Authentifizierung läuft über \textbf{JSON Web Tokens} (JWT). Der Vorteil: -zustandslose Sessions, bei denen der Server keine Session-Daten speichern muss. +Die Authentifizierung erfolgt über einen \textbf{X-User-Id Header}, der bei +jedem Request die User-ID mitschickt. Diese einfache Lösung reicht für den +aktuellen Entwicklungsstand aus. Geplant ist außerdem die Unterstützung des \textbf{iCalendar}-Formats (ICAL) für den Export von Kalender-Events. @@ -157,7 +158,7 @@ Notiz-Feld) und ChatMessage. Der Controller Layer bildet die Schnittstelle zwischen Frontend und Backend-Logik. Die Routes definieren die API-Endpunkte, die Controller verarbeiten die eingehenden Requests und reichen diese an die Services weiter. -Eine Auth Middleware prüft bei geschützten Routen den JWT-Token. +Eine Auth Middleware prüft bei geschützten Routen den X-User-Id Header. \subsubsection{Service Layer} diff --git a/package-lock.json b/package-lock.json index 4164633..d13ec2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -72,7 +72,6 @@ "dotenv": "^16.4.7", "express": "^5.2.1", "ical.js": "^2.2.1", - "jsonwebtoken": "^9.0.3", "mongoose": "^9.1.1", "openai": "^6.15.0", "pino": "^10.1.1", @@ -85,7 +84,6 @@ "@types/express": "^5.0.6", "@types/ical": "^0.8.3", "@types/jest": "^30.0.0", - "@types/jsonwebtoken": "^9.0.10", "@types/node": "^24.10.1", "jest": "^30.2.0", "pino-pretty": "^13.1.3", @@ -4936,20 +4934,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*", - "@types/node": "*" - } - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "24.10.1", "license": "MIT", @@ -6076,10 +6060,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "license": "BSD-3-Clause" - }, "node_modules/buffer-from": { "version": "1.1.2", "license": "MIT" @@ -6844,13 +6824,6 @@ "dev": true, "license": "MIT" }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, "node_modules/ee-first": { "version": "1.1.1", "license": "MIT" @@ -13280,36 +13253,6 @@ "node": ">=6" } }, - "node_modules/jsonwebtoken": { - "version": "9.0.3", - "license": "MIT", - "dependencies": { - "jws": "^4.0.1", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jsonwebtoken/node_modules/semver": { - "version": "7.7.3", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "dev": true, @@ -13324,23 +13267,6 @@ "node": ">=4.0" } }, - "node_modules/jwa": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "4.0.1", - "license": "MIT", - "dependencies": { - "jwa": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, "node_modules/kareem": { "version": "3.0.0", "license": "Apache-2.0", @@ -13502,30 +13428,6 @@ "version": "4.0.8", "license": "MIT" }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "license": "MIT" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -13538,10 +13440,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.once": { - "version": "4.1.1", - "license": "MIT" - }, "node_modules/lodash.throttle": { "version": "4.1.1", "license": "MIT"