fix: save and send cookie in dev setup

This commit is contained in:
eneller
2026-03-08 20:39:04 +01:00
parent c9a2cd8d66
commit fa2203927a
7 changed files with 44 additions and 27 deletions

View File

@@ -1,8 +1,10 @@
# FakeMoney # FakeMoney
A PayPal-like payment processor for virtual money, intended to be used for simulation games. A PayPal-like payment processor for virtual money, intended to be used for simulation games.
## Frontend ## Development
### Frontend
Is written in angular + bootstrap. Is written in angular + bootstrap.
## Backend ### Backend
Uses NextJS + PostgreSQL. Uses NextJS + PostgreSQL with JWT as cookies.

View File

@@ -65,6 +65,9 @@
"defaultConfiguration": "production" "defaultConfiguration": "production"
}, },
"serve": { "serve": {
"options": {
"proxyConfig": "proxy.json"
},
"builder": "@angular/build:dev-server", "builder": "@angular/build:dev-server",
"configurations": { "configurations": {
"production": { "production": {

8
client/proxy.json Normal file
View File

@@ -0,0 +1,8 @@
{
"/api": {
"target": "http://localhost:3000",
"secure": false,
"changeOrigin": true,
"withCredentials": true
}
}

View File

@@ -7,20 +7,20 @@ import Transaction from '@model/transaction'
providedIn: 'root', providedIn: 'root',
}) })
export class APIService { export class APIService {
private apiUrl = 'http://localhost:3000/api' private apiUrl = '/api';
private isAuthenticatedSubject = new BehaviorSubject<boolean>(false); private isAuthenticatedSubject = new BehaviorSubject<boolean>(false);
isAuthenticated$ = this.isAuthenticatedSubject.asObservable(); isAuthenticated$ = this.isAuthenticatedSubject.asObservable();
constructor(private http: HttpClient){} constructor(private http: HttpClient){}
getTransactions(): Observable<Transaction[]>{ getTransactions(): Observable<Transaction[]>{
return this.http.get<Transaction[]>(this.apiUrl + '/transactions'); return this.http.get<Transaction[]>(`${this.apiUrl}/transactions`);
} }
login(username: string, password: string): Observable<any>{ login(username: string, password: string): Observable<any>{
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<any>{ logout(): Observable<any>{
return this.http.post(this.apiUrl + '/auth/logout', {}); return this.http.post(`${this.apiUrl}/auth/logout`, {});
} }
checkAuthStatus(): Observable<boolean> { checkAuthStatus(): Observable<boolean> {
return this.http.get(`${this.apiUrl}/auth/status`, { withCredentials: true}).pipe( return this.http.get(`${this.apiUrl}/auth/status`, { withCredentials: true}).pipe(

View File

@@ -7,6 +7,7 @@ import { db, testConnection } from "./util/db";
import { logger } from "./util/logging"; import { logger } from "./util/logging";
const app: Express = express(); const app: Express = express();
// TODO replace with frontend URL
app.use(cors({ origin: 'http://localhost:4200', credentials: true})); app.use(cors({ origin: 'http://localhost:4200', credentials: true}));
app.use(cookieParser()); app.use(cookieParser());
app.use(express.json()); app.use(express.json());
@@ -20,12 +21,12 @@ app.use('/api/auth', authRouter);
const PORT: number = parseInt(process.env.PORT as string) || 3000; const PORT: number = parseInt(process.env.PORT as string) || 3000;
// Start server after DB connection is established
async function startServer() { async function startServer() {
await testConnection(); // Test DB connection first await testConnection();
// Sync models (use migrations in production!) // 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, () => { app.listen(PORT, () => {
logger.info(`🚀 Backend Server running on http://localhost:${PORT}`); logger.info(`🚀 Backend Server running on http://localhost:${PORT}`);

View File

@@ -1,7 +1,7 @@
import express, { Request } from 'express'; import express, { Request } from 'express';
import { logger } from '../util/logging'; import { logger } from '../util/logging';
import User from '../model/user'; import User from '../model/user';
import { JWT, JWK } from 'ts-jose'; import { getJWT, checkJWT } from '../util/auth';
const router = express.Router(); const router = express.Router();
@@ -16,12 +16,12 @@ router.post('/login', async (req, res) => {
if (!isMatch) return res.status(401).json({ message: 'Invalid credentials' }); if (!isMatch) return res.status(401).json({ message: 'Invalid credentials' });
// successfully authenticated // successfully authenticated
res.cookie('jwt', 'toekn', { // TODO change this for production setup
/* res.cookie('jwt', getJWT(user), {
httpOnly: true, // Prevent XSS httpOnly: true, // Prevent XSS
secure: true, // HTTPS only secure: false, // HTTPS only
sameSite: 'strict', // CSRF protection sameSite: 'lax', // CSRF protection
*/ domain: '.localhost',
maxAge: 86400000, // 1 day maxAge: 86400000, // 1 day
}); });
res.json({ message: 'Logged in successfully' }); res.json({ message: 'Logged in successfully' });
@@ -37,20 +37,10 @@ router.post('/logout', (req, res) => {
}); });
router.get('/status', (req, res) => { router.get('/status', (req, res) => {
console.log(req.cookies); if (checkJWT(req)){
if (isAuthenticated(req)){
return res.status(200).json({authenticated: true}); return res.status(200).json({authenticated: true});
} }
return res.status(401).json({authenticated: false}); 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; export default router;

13
server/src/util/auth.ts Normal file
View File

@@ -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'
}