feat: Security
This commit is contained in:
72
server/src/middleware/require-auth.ts
Normal file
72
server/src/middleware/require-auth.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import '../types/express-augmentation';
|
||||
import {
|
||||
NextFunction,
|
||||
Request,
|
||||
Response
|
||||
} from 'express';
|
||||
import { consumeSessionToken } from '../services/session-auth.service';
|
||||
|
||||
function readBearerToken(req: Request): string | null {
|
||||
const header = req.header('authorization');
|
||||
|
||||
if (!header || !header.toLowerCase().startsWith('bearer ')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const token = header.slice(7).trim();
|
||||
|
||||
return token || null;
|
||||
}
|
||||
|
||||
export async function requireAuth(req: Request, res: Response, next: NextFunction): Promise<void> {
|
||||
const token = readBearerToken(req);
|
||||
|
||||
if (!token) {
|
||||
res.status(401).json({ error: 'Missing or invalid authorization token', errorCode: 'UNAUTHORIZED' });
|
||||
return;
|
||||
}
|
||||
|
||||
const session = await consumeSessionToken(token);
|
||||
|
||||
if (!session) {
|
||||
res.status(401).json({ error: 'Missing or invalid authorization token', errorCode: 'UNAUTHORIZED' });
|
||||
return;
|
||||
}
|
||||
|
||||
req.authToken = session.token;
|
||||
req.authUserId = session.user.id;
|
||||
req.authUser = session.user;
|
||||
next();
|
||||
}
|
||||
|
||||
export function getAuthenticatedUserId(req: Request): string {
|
||||
const userId = req.authUserId;
|
||||
|
||||
if (!userId) {
|
||||
throw new Error('Authenticated user id missing after requireAuth');
|
||||
}
|
||||
|
||||
return userId;
|
||||
}
|
||||
|
||||
export function rejectSpoofedUserId(
|
||||
req: Request,
|
||||
res: Response,
|
||||
bodyUserId: unknown,
|
||||
fieldName: string
|
||||
): bodyUserId is string {
|
||||
if (typeof bodyUserId !== 'string' || !bodyUserId.trim()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bodyUserId !== req.authUserId) {
|
||||
res.status(400).json({
|
||||
error: `${fieldName} must match the authenticated user`,
|
||||
errorCode: 'USER_ID_MISMATCH'
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user