From fa2203927a8df9234a68d8b871f392a5450a1209 Mon Sep 17 00:00:00 2001 From: eneller Date: Sun, 8 Mar 2026 20:39:04 +0100 Subject: [PATCH] fix: save and send cookie in dev setup --- README.md | 8 +++++--- client/angular.json | 3 +++ client/proxy.json | 8 ++++++++ client/src/app/services/api.ts | 8 ++++---- server/src/index.ts | 7 ++++--- server/src/routes/auth.ts | 24 +++++++----------------- server/src/util/auth.ts | 13 +++++++++++++ 7 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 client/proxy.json create mode 100644 server/src/util/auth.ts diff --git a/README.md b/README.md index fc71671..7bf8b23 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # FakeMoney A PayPal-like payment processor for virtual money, intended to be used for simulation games. -## Frontend +## Development + +### Frontend Is written in angular + bootstrap. -## Backend -Uses NextJS + PostgreSQL. \ No newline at end of file +### Backend +Uses NextJS + PostgreSQL with JWT as cookies. \ No newline at end of file diff --git a/client/angular.json b/client/angular.json index eabedc8..58472a4 100644 --- a/client/angular.json +++ b/client/angular.json @@ -65,6 +65,9 @@ "defaultConfiguration": "production" }, "serve": { + "options": { + "proxyConfig": "proxy.json" + }, "builder": "@angular/build:dev-server", "configurations": { "production": { diff --git a/client/proxy.json b/client/proxy.json new file mode 100644 index 0000000..2cac925 --- /dev/null +++ b/client/proxy.json @@ -0,0 +1,8 @@ +{ + "/api": { + "target": "http://localhost:3000", + "secure": false, + "changeOrigin": true, + "withCredentials": true + } +} diff --git a/client/src/app/services/api.ts b/client/src/app/services/api.ts index 69007ba..e29e5af 100644 --- a/client/src/app/services/api.ts +++ b/client/src/app/services/api.ts @@ -7,20 +7,20 @@ import Transaction from '@model/transaction' providedIn: 'root', }) export class APIService { - private apiUrl = 'http://localhost:3000/api' + private apiUrl = '/api'; private isAuthenticatedSubject = new BehaviorSubject(false); isAuthenticated$ = this.isAuthenticatedSubject.asObservable(); constructor(private http: HttpClient){} getTransactions(): Observable{ - return this.http.get(this.apiUrl + '/transactions'); + return this.http.get(`${this.apiUrl}/transactions`); } login(username: string, password: string): Observable{ - return this.http.post(this.apiUrl + '/auth/login',{ 'username': username, 'password': password}); + return this.http.post(`${this.apiUrl}/auth/login`,{ 'username': username, 'password': password}); } logout(): Observable{ - return this.http.post(this.apiUrl + '/auth/logout', {}); + return this.http.post(`${this.apiUrl}/auth/logout`, {}); } checkAuthStatus(): Observable { return this.http.get(`${this.apiUrl}/auth/status`, { withCredentials: true}).pipe( diff --git a/server/src/index.ts b/server/src/index.ts index abdd633..eacf787 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -7,6 +7,7 @@ import { db, testConnection } from "./util/db"; import { logger } from "./util/logging"; const app: Express = express(); +// TODO replace with frontend URL app.use(cors({ origin: 'http://localhost:4200', credentials: true})); app.use(cookieParser()); app.use(express.json()); @@ -20,12 +21,12 @@ app.use('/api/auth', authRouter); const PORT: number = parseInt(process.env.PORT as string) || 3000; -// Start server after DB connection is established async function startServer() { - await testConnection(); // Test DB connection first + await testConnection(); // Sync models (use migrations in production!) - await db.sync({ alter: true }); // Use { force: true } to drop and recreate tables (development only!) + // Use { force: true } to drop and recreate tables (development only!) + await db.sync({ alter: true }); app.listen(PORT, () => { logger.info(`🚀 Backend Server running on http://localhost:${PORT}`); diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index abccbce..de76044 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -1,7 +1,7 @@ import express, { Request } from 'express'; import { logger } from '../util/logging'; import User from '../model/user'; -import { JWT, JWK } from 'ts-jose'; +import { getJWT, checkJWT } from '../util/auth'; const router = express.Router(); @@ -16,12 +16,12 @@ router.post('/login', async (req, res) => { if (!isMatch) return res.status(401).json({ message: 'Invalid credentials' }); // successfully authenticated - res.cookie('jwt', 'toekn', { - /* + // TODO change this for production setup + res.cookie('jwt', getJWT(user), { httpOnly: true, // Prevent XSS - secure: true, // HTTPS only - sameSite: 'strict', // CSRF protection - */ + secure: false, // HTTPS only + sameSite: 'lax', // CSRF protection + domain: '.localhost', maxAge: 86400000, // 1 day }); res.json({ message: 'Logged in successfully' }); @@ -37,20 +37,10 @@ router.post('/logout', (req, res) => { }); router.get('/status', (req, res) => { - console.log(req.cookies); - if (isAuthenticated(req)){ + if (checkJWT(req)){ return res.status(200).json({authenticated: true}); } return res.status(401).json({authenticated: false}); }) -function isAuthenticated(req: Request){ - // TODO check JWT - return req.cookies.jwt -} - -function getJWT(user: User){ - -} - export default router; diff --git a/server/src/util/auth.ts b/server/src/util/auth.ts new file mode 100644 index 0000000..0a0038a --- /dev/null +++ b/server/src/util/auth.ts @@ -0,0 +1,13 @@ +import { Request } from "express" +import User from "../model/user" +import { JWT, JWK } from 'ts-jose'; + +const privateKey = process.env.FM_PRIVATE_KEY; +export function checkJWT(req: Request){ + // TODO check JWT + return req.cookies.jwt +} + +export function getJWT(user: User){ + return 'toekn' +} \ No newline at end of file