← back to Wine Finder Next
app/api/security/test/route.ts
377 lines
// Security Test Endpoint - Comprehensive validation of security features
import { NextRequest, NextResponse } from 'next/server';
import { verifyJWT, createJWT } from '@/lib/jwtAuth';
import { generateCSRFToken, verifyCSRFToken } from '@/lib/csrf';
import { createSession, verifySession, getSessionStats } from '@/lib/sessionManagement';
import { generateTOTPSecret, verifyTOTP, get2FAStatus } from '@/lib/twoFactorAuth';
import { generateAPIKey, signRequest, verifySignedRequest } from '@/lib/requestSigning';
import { extractAPIVersion, validateAPIVersion } from '@/lib/apiVersioning';
import { detectSQLInjection, detectXSS, getSecurityDashboard } from '@/lib/securityMonitoring';
import { comprehensiveSecurityCheck } from '@/lib/advancedSecurity';
import { checkRateLimit, getRateLimitConfig, getClientIdentifier } from '@/lib/rateLimit';
export async function GET(request: NextRequest) {
try {
const testResults: any = {
timestamp: new Date().toISOString(),
tests: [],
summary: { passed: 0, failed: 0, warnings: 0 }
};
// Helper function to add test result
const addTest = (name: string, passed: boolean, details: any, warning?: boolean) => {
testResults.tests.push({
name,
status: passed ? 'PASS' : (warning ? 'WARN' : 'FAIL'),
details
});
if (passed && !warning) testResults.summary.passed++;
else if (warning) testResults.summary.warnings++;
else testResults.summary.failed++;
};
// Extract client info
const clientIp = getClientIdentifier(request);
// 1. Test JWT Authentication
try {
const testJWT = createJWT('test_user', 'test@winedao.com', 'member');
const jwtVerification = verifyJWT(testJWT);
addTest('JWT Authentication', jwtVerification.valid, {
tokenGenerated: !!testJWT,
verification: jwtVerification
});
} catch (error: any) {
addTest('JWT Authentication', false, { error: error.message });
}
// 2. Test CSRF Protection
try {
const csrfToken = generateCSRFToken('test_session', clientIp);
const csrfVerification = verifyCSRFToken(csrfToken, 'test_session', clientIp);
addTest('CSRF Protection', csrfVerification.valid, {
tokenGenerated: !!csrfToken,
verification: csrfVerification
});
} catch (error: any) {
addTest('CSRF Protection', false, { error: error.message });
}
// 3. Test Session Management
try {
const { session, token } = createSession(
'test_user',
clientIp,
request.headers.get('user-agent') || 'test-agent'
);
const sessionVerification = verifySession(token, clientIp);
const stats = getSessionStats();
addTest('Session Management', sessionVerification.valid, {
sessionCreated: !!session,
verification: sessionVerification,
stats
});
} catch (error: any) {
addTest('Session Management', false, { error: error.message });
}
// 4. Test 2FA Setup (without actually enabling)
try {
const totpSetup = generateTOTPSecret('test_user');
const status = get2FAStatus('test_user');
addTest('Two-Factor Auth', true, {
setupAvailable: !!totpSetup.secret,
qrCodeGenerated: !!totpSetup.qrCode,
backupCodesCount: totpSetup.backupCodes.length,
currentStatus: status
});
} catch (error: any) {
addTest('Two-Factor Auth', false, { error: error.message });
}
// 5. Test Request Signing
try {
const { apiKey, apiSecret } = generateAPIKey('test_user', 'test_key', ['read']);
const signed = signRequest(apiSecret, 'POST', '/api/test', { test: true });
addTest('Request Signing', true, {
apiKeyGenerated: !!apiKey,
signatureGenerated: !!signed.signature,
timestampValid: Math.abs(signed.timestamp - Date.now()) < 1000
});
} catch (error: any) {
addTest('Request Signing', false, { error: error.message });
}
// 6. Test API Versioning
try {
const version = extractAPIVersion(request);
const validation = validateAPIVersion(version.version);
addTest('API Versioning', validation.valid, {
detectedVersion: version,
validation,
supportedVersions: ['v1', 'v2', 'v3']
}, validation.warnings && validation.warnings.length > 0);
} catch (error: any) {
addTest('API Versioning', false, { error: error.message });
}
// 7. Test SQL Injection Detection
try {
const maliciousInputs = [
"'; DROP TABLE users; --",
"1' OR '1'='1",
"admin'--",
"1 UNION SELECT * FROM users"
];
const detections = maliciousInputs.map(input => ({
input,
detected: detectSQLInjection(input)
}));
const allDetected = detections.every(d => d.detected);
addTest('SQL Injection Detection', allDetected, {
testedInputs: detections,
allBlocked: allDetected
});
} catch (error: any) {
addTest('SQL Injection Detection', false, { error: error.message });
}
// 8. Test XSS Detection
try {
const xssInputs = [
"<script>alert('XSS')</script>",
"javascript:alert('XSS')",
"<img src=x onerror=alert('XSS')>",
"<iframe src='evil.com'></iframe>"
];
const detections = xssInputs.map(input => ({
input,
detected: detectXSS(input)
}));
const allDetected = detections.every(d => d.detected);
addTest('XSS Detection', allDetected, {
testedInputs: detections,
allBlocked: allDetected
});
} catch (error: any) {
addTest('XSS Detection', false, { error: error.message });
}
// 9. Test Rate Limiting
try {
const config = getRateLimitConfig('/api/security/test');
const rateLimit = checkRateLimit(clientIp, config);
addTest('Rate Limiting', rateLimit.success, {
limit: rateLimit.limit,
remaining: rateLimit.remaining,
resetTime: new Date(rateLimit.reset).toISOString()
}, rateLimit.remaining < 10);
} catch (error: any) {
addTest('Rate Limiting', false, { error: error.message });
}
// 10. Test Advanced Security Check
try {
const securityCheck = comprehensiveSecurityCheck({
ip: clientIp,
headers: Object.fromEntries(request.headers),
method: request.method,
path: request.nextUrl.pathname
});
addTest('Advanced Security', securityCheck.allowed, {
riskScore: securityCheck.riskScore,
actions: securityCheck.actions,
reason: securityCheck.reason
}, securityCheck.riskScore > 50);
} catch (error: any) {
addTest('Advanced Security', false, { error: error.message });
}
// 11. Test Security Headers
try {
const requiredHeaders = [
'x-frame-options',
'x-content-type-options',
'x-xss-protection',
'strict-transport-security',
'content-security-policy'
];
const responseHeaders = new Headers();
// These would be set by middleware in production
responseHeaders.set('x-frame-options', 'SAMEORIGIN');
responseHeaders.set('x-content-type-options', 'nosniff');
responseHeaders.set('x-xss-protection', '1; mode=block');
responseHeaders.set('strict-transport-security', 'max-age=63072000');
responseHeaders.set('content-security-policy', "default-src 'self'");
const headersPresent = requiredHeaders.map(header => ({
header,
present: responseHeaders.has(header),
value: responseHeaders.get(header)
}));
const allPresent = headersPresent.every(h => h.present);
addTest('Security Headers', allPresent, {
headers: headersPresent,
allConfigured: allPresent
});
} catch (error: any) {
addTest('Security Headers', false, { error: error.message });
}
// 12. Get Security Dashboard Summary
try {
const dashboard = getSecurityDashboard();
addTest('Security Monitoring', true, {
totalEvents: dashboard.stats.total,
last24h: dashboard.stats.last24h,
blockedIPs: dashboard.blockedIPs.length,
suspiciousIPs: dashboard.suspiciousIPs.length
}, dashboard.stats.last24h > 100);
} catch (error: any) {
addTest('Security Monitoring', false, { error: error.message });
}
// Calculate overall score
const totalTests = testResults.summary.passed + testResults.summary.failed + testResults.summary.warnings;
const score = Math.round((testResults.summary.passed / totalTests) * 100);
testResults.summary.score = score;
testResults.summary.status = score >= 90 ? 'EXCELLENT' :
score >= 75 ? 'GOOD' :
score >= 50 ? 'FAIR' : 'POOR';
// Add recommendations
testResults.recommendations = [];
if (testResults.summary.failed > 0) {
testResults.recommendations.push('Fix failed security tests immediately');
}
if (testResults.summary.warnings > 0) {
testResults.recommendations.push('Review and address security warnings');
}
if (score < 90) {
testResults.recommendations.push('Implement additional security hardening measures');
}
// Add test endpoint notice
testResults.notice = 'This is a security test endpoint. Some features are simulated for testing purposes.';
return NextResponse.json({
success: true,
data: testResults
});
} catch (error) {
console.error('[Security Test Error]', error);
return NextResponse.json({
success: false,
error: 'Security test failed',
details: error instanceof Error ? error.message : 'Unknown error'
}, { status: 500 });
}
}
// POST endpoint to test CSRF and request signing
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const headers = Object.fromEntries(request.headers);
const testResults: any = {
timestamp: new Date().toISOString(),
method: 'POST',
tests: []
};
// Test CSRF verification
const csrfToken = headers['x-csrf-token'];
if (csrfToken) {
const verification = verifyCSRFToken(csrfToken);
testResults.tests.push({
name: 'CSRF Verification',
status: verification.valid ? 'PASS' : 'FAIL',
details: verification
});
} else {
testResults.tests.push({
name: 'CSRF Verification',
status: 'SKIP',
details: { reason: 'No CSRF token provided' }
});
}
// Test request signing
if (headers['x-signature']) {
const verification = verifySignedRequest(
headers,
'POST',
request.nextUrl.pathname,
body
);
testResults.tests.push({
name: 'Request Signature',
status: verification.valid ? 'PASS' : 'FAIL',
details: verification
});
} else {
testResults.tests.push({
name: 'Request Signature',
status: 'SKIP',
details: { reason: 'No signature provided' }
});
}
// Test input validation
const validationTests = [
{
name: 'SQL Injection Check',
value: JSON.stringify(body),
detected: detectSQLInjection(JSON.stringify(body))
},
{
name: 'XSS Check',
value: JSON.stringify(body),
detected: detectXSS(JSON.stringify(body))
}
];
validationTests.forEach(test => {
testResults.tests.push({
name: test.name,
status: test.detected ? 'FAIL' : 'PASS',
details: { detected: test.detected }
});
});
return NextResponse.json({
success: true,
data: testResults
});
} catch (error) {
return NextResponse.json({
success: false,
error: 'POST test failed',
details: error instanceof Error ? error.message : 'Unknown error'
}, { status: 500 });
}
}