feat(auth): implement session token creation and verification for enhanced security

feat(api): require session authentication for admin routes and improve error handling

fix(api): streamline project image generation by fetching data directly from the database

fix(api): optimize project import/export functionality with session validation and improved error handling

fix(api): enhance analytics dashboard and email manager with session token for admin requests

fix(components): improve loading states and dynamic imports for better user experience

chore(security): update Content Security Policy to avoid unsafe-eval in production

chore(deps): update package.json scripts for consistent environment handling in linting and testing
This commit is contained in:
2026-01-12 00:27:03 +01:00
parent 9cc03bc475
commit 0349c686fa
25 changed files with 423 additions and 268 deletions

View File

@@ -37,7 +37,13 @@ export async function POST(request: NextRequest) {
}
// Get admin credentials from environment
const adminAuth = process.env.ADMIN_BASIC_AUTH || 'admin:default_password_change_me';
const adminAuth = process.env.ADMIN_BASIC_AUTH;
if (!adminAuth || adminAuth.trim() === '' || adminAuth === 'admin:default_password_change_me') {
return new NextResponse(
JSON.stringify({ error: 'Admin auth is not configured' }),
{ status: 503, headers: { 'Content-Type': 'application/json' } }
);
}
const [, expectedPassword] = adminAuth.split(':');
// Secure password comparison using constant-time comparison
@@ -48,22 +54,14 @@ export async function POST(request: NextRequest) {
// Use constant-time comparison to prevent timing attacks
if (passwordBuffer.length === expectedBuffer.length &&
crypto.timingSafeEqual(passwordBuffer, expectedBuffer)) {
// Generate cryptographically secure session token
const timestamp = Date.now();
const randomBytes = crypto.randomBytes(32);
const randomString = randomBytes.toString('hex');
// Create session data
const sessionData = {
timestamp,
random: randomString,
ip: ip,
userAgent: request.headers.get('user-agent') || 'unknown'
};
// Encode session data (base64 is sufficient for this use case)
const sessionJson = JSON.stringify(sessionData);
const sessionToken = Buffer.from(sessionJson).toString('base64');
const { createSessionToken } = await import('@/lib/auth');
const sessionToken = createSessionToken(request);
if (!sessionToken) {
return new NextResponse(
JSON.stringify({ error: 'Session secret not configured' }),
{ status: 503, headers: { 'Content-Type': 'application/json' } }
);
}
return new NextResponse(
JSON.stringify({