🔧 Update Admin Dashboard and Authentication Flow

 Updated Admin Dashboard URL:
- Changed the Admin Dashboard access path from `/admin` to `/manage` in multiple files for consistency.

 Enhanced Middleware Authentication:
- Updated middleware to protect new admin routes including `/manage` and `/dashboard`.

 Implemented CSRF Protection:
- Added CSRF token generation and validation for login and session validation routes.

 Introduced Rate Limiting:
- Added rate limiting for admin routes and CSRF token requests to enhance security.

 Refactored Admin Page:
- Created a new admin management page with improved authentication handling and user feedback.

🎯 Overall Improvements:
- Strengthened security measures for admin access.
- Improved user experience with clearer navigation and feedback.
- Streamlined authentication processes for better performance.
This commit is contained in:
2025-09-08 09:38:01 +02:00
parent 087f3dc5e3
commit 0ae1883cf4
15 changed files with 862 additions and 52 deletions

74
lib/auth.ts Normal file
View File

@@ -0,0 +1,74 @@
import { NextRequest } from 'next/server';
// Server-side authentication utilities
export function verifyAdminAuth(request: NextRequest): boolean {
// Check for basic auth header
const authHeader = request.headers.get('authorization');
if (!authHeader || !authHeader.startsWith('Basic ')) {
return false;
}
try {
const base64Credentials = authHeader.split(' ')[1];
const credentials = atob(base64Credentials);
const [username, password] = credentials.split(':');
// Get admin credentials from environment
const adminAuth = process.env.ADMIN_BASIC_AUTH || 'admin:default_password_change_me';
const [expectedUsername, expectedPassword] = adminAuth.split(':');
return username === expectedUsername && password === expectedPassword;
} catch (error) {
return false;
}
}
export function requireAdminAuth(request: NextRequest): Response | null {
if (!verifyAdminAuth(request)) {
return new Response(
JSON.stringify({ error: 'Unauthorized' }),
{
status: 401,
headers: {
'Content-Type': 'application/json',
'WWW-Authenticate': 'Basic realm="Admin Access"'
}
}
);
}
return null;
}
// Rate limiting for admin endpoints
const rateLimitMap = new Map<string, { count: number; resetTime: number }>();
export function checkRateLimit(ip: string, maxRequests: number = 10, windowMs: number = 60000): boolean {
const now = Date.now();
const key = `admin_${ip}`;
const current = rateLimitMap.get(key);
if (!current || now > current.resetTime) {
rateLimitMap.set(key, { count: 1, resetTime: now + windowMs });
return true;
}
if (current.count >= maxRequests) {
return false;
}
current.count++;
return true;
}
export function getRateLimitHeaders(ip: string, maxRequests: number = 10, windowMs: number = 60000): Record<string, string> {
const current = rateLimitMap.get(`admin_${ip}`);
const remaining = current ? Math.max(0, maxRequests - current.count) : maxRequests;
return {
'X-RateLimit-Limit': maxRequests.toString(),
'X-RateLimit-Remaining': remaining.toString(),
'X-RateLimit-Reset': current ? Math.ceil(current.resetTime / 1000).toString() : Math.ceil((Date.now() + windowMs) / 1000).toString()
};
}