Security Monitoring & Auditing

Audit logging, security monitoring, and threat detection for Smart Shelf.

Security Monitoring & Auditing

This section covers comprehensive security monitoring, audit logging, and threat detection mechanisms in Smart Shelf.

Audit Logging System

Audit Event Structure

// lib/audit/logger.ts
export interface AuditEvent {
  action: string;
  resource: string;
  resourceId?: string;
  userId: string;
  ipAddress?: string;
  userAgent?: string;
  details?: any;
  timestamp: Date;
}

export async function logAuditEvent(event: AuditEvent): Promise<void> {
  const supabase = createServiceRoleClient();
  
  try {
    await supabase.from('audit_logs').insert({
      action: event.action,
      resource: event.resource,
      resource_id: event.resourceId,
      user_id: event.userId,
      ip_address: event.ipAddress,
      user_agent: event.userAgent,
      details: event.details,
      created_at: event.timestamp.toISOString(),
    });
  } catch (error) {
    // Log to external service if database is unavailable
    console.error('Audit logging failed:', error);
  }
}

Automatic Audit Middleware

// Middleware for automatic audit logging
export function withAuditLog(action: string, resource: string) {
  return function(handler: (req: NextRequest, user: User) => Promise<NextResponse>) {
    return async function(req: NextRequest) {
      const user = await validateAuth(req);
      
      try {
        const response = await handler(req, user);
        
        // Log successful action
        await logAuditEvent({
          action,
          resource,
          userId: user.id,
          ipAddress: req.headers.get('x-forwarded-for') || req.ip,
          userAgent: req.headers.get('user-agent'),
          timestamp: new Date(),
        });
        
        return response;
        
      } catch (error) {
        // Log failed action
        await logAuditEvent({
          action: `${action}_failed`,
          resource,
          userId: user.id,
          ipAddress: req.headers.get('x-forwarded-for') || req.ip,
          userAgent: req.headers.get('user-agent'),
          details: { error: error.message },
          timestamp: new Date(),
        });
        
        throw error;
      }
    };
  };
}

// Usage example
export const POST = withAuditLog('create', 'product')(async (req, user) => {
  // Create product logic
});

Security Headers and Protection

Security Headers Implementation

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const response = NextResponse.next();
  
  // Security Headers
  response.headers.set('X-Frame-Options', 'DENY');
  response.headers.set('X-Content-Type-Options', 'nosniff');
  response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
  response.headers.set('X-XSS-Protection', '1; mode=block');
  
  // Content Security Policy
  const csp = [
    "default-src 'self'",
    "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net",
    "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
    "font-src 'self' https://fonts.gstatic.com",
    "img-src 'self' data: https:",
    "connect-src 'self' https://*.supabase.co wss://*.supabase.co",
    "object-src 'none'",
    "base-uri 'self'",
    "form-action 'self'",
    "frame-ancestors 'none'",
  ].join('; ');
  
  response.headers.set('Content-Security-Policy', csp);
  
  return response;
}

CSRF Protection

// CSRF Protection for state-changing requests
if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(request.method)) {
  const origin = request.headers.get('origin');
  const host = request.headers.get('host');
  
  if (!origin || !host || !origin.includes(host)) {
    return NextResponse.json(
      { error: 'Invalid origin' },
      { status: 403 }
    );
  }
}

Rate Limiting and Abuse Prevention

API Rate Limiting

// lib/security/rate-limit.ts
import { Redis } from 'ioredis';

const redis = new Redis(process.env.REDIS_URL!);

interface RateLimit {
  windowMs: number;  // Time window in milliseconds
  maxRequests: number;  // Maximum requests per window
}

const RATE_LIMITS: Record<string, RateLimit> = {
  login: { windowMs: 15 * 60 * 1000, maxRequests: 5 }, // 5 attempts per 15 minutes
  api: { windowMs: 60 * 1000, maxRequests: 100 }, // 100 requests per minute
  upload: { windowMs: 60 * 1000, maxRequests: 10 }, // 10 uploads per minute
};

export async function checkRateLimit(
  identifier: string,
  limitType: keyof typeof RATE_LIMITS
): Promise<{ allowed: boolean; remaining: number; resetTime: number }> {
  const limit = RATE_LIMITS[limitType];
  const key = `rate_limit:${limitType}:${identifier}`;
  
  const current = await redis.get(key);
  const requests = current ? parseInt(current) : 0;
  
  if (requests >= limit.maxRequests) {
    const ttl = await redis.ttl(key);
    return {
      allowed: false,
      remaining: 0,
      resetTime: Date.now() + (ttl * 1000),
    };
  }
  
  // Increment counter
  const pipeline = redis.pipeline();
  pipeline.incr(key);
  pipeline.expire(key, Math.ceil(limit.windowMs / 1000));
  await pipeline.exec();
  
  return {
    allowed: true,
    remaining: limit.maxRequests - requests - 1,
    resetTime: Date.now() + limit.windowMs,
  };
}

// Rate limiting middleware
export function withRateLimit(limitType: keyof typeof RATE_LIMITS) {
  return function(handler: Function) {
    return async function(req: NextRequest) {
      const identifier = req.headers.get('x-forwarded-for') || req.ip || 'unknown';
      const rateLimit = await checkRateLimit(identifier, limitType);
      
      if (!rateLimit.allowed) {
        return NextResponse.json(
          { error: 'Rate limit exceeded' },
          { 
            status: 429,
            headers: {
              'Retry-After': Math.ceil((rateLimit.resetTime - Date.now()) / 1000).toString(),
              'X-RateLimit-Remaining': '0',
              'X-RateLimit-Reset': rateLimit.resetTime.toString(),
            }
          }
        );
      }
      
      const response = await handler(req);
      
      // Add rate limit headers to successful responses
      response.headers.set('X-RateLimit-Remaining', rateLimit.remaining.toString());
      response.headers.set('X-RateLimit-Reset', rateLimit.resetTime.toString());
      
      return response;
    };
  };
}

Threat Detection and Monitoring

Suspicious Activity Detection

// lib/security/threat-detection.ts
export interface SecurityEvent {
  type: 'failed_login' | 'suspicious_access' | 'data_breach_attempt' | 'privilege_escalation';
  severity: 'low' | 'medium' | 'high' | 'critical';
  userId?: string;
  ipAddress: string;
  userAgent?: string;
  details: any;
  timestamp: Date;
}

export async function detectThreats(event: SecurityEvent): Promise<void> {
  // Log security event
  await logSecurityEvent(event);
  
  // Check for patterns
  switch (event.type) {
    case 'failed_login':
      await checkFailedLoginPattern(event);
      break;
    case 'suspicious_access':
      await checkAccessPattern(event);
      break;
    case 'privilege_escalation':
      await alertAdministrators(event);
      break;
  }
}

async function checkFailedLoginPattern(event: SecurityEvent): Promise<void> {
  const recentFailures = await getRecentSecurityEvents(
    event.ipAddress,
    'failed_login',
    15 * 60 * 1000 // 15 minutes
  );
  
  if (recentFailures.length >= 5) {
    // Block IP temporarily
    await blockIpAddress(event.ipAddress, 60 * 60 * 1000); // 1 hour
    
    // Alert administrators
    await alertAdministrators({
      ...event,
      type: 'failed_login',
      severity: 'high',
      details: {
        ...event.details,
        pattern: 'brute_force_attempt',
        failureCount: recentFailures.length,
      },
    });
  }
}

async function alertAdministrators(event: SecurityEvent): Promise<void> {
  // Send alert to administrators
  const admins = await getAdministrators();
  
  for (const admin of admins) {
    await sendSecurityAlert(admin.email, {
      subject: `Security Alert: ${event.type}`,
      priority: event.severity,
      details: event,
    });
  }
  
  // Log to external monitoring service
  await logToMonitoringService(event);
}

Real-time Monitoring Dashboard

// lib/monitoring/dashboard.ts
export async function getSecurityMetrics(timeRange: string) {
  const supabase = createServiceRoleClient();
  
  const [
    failedLogins,
    suspiciousActivities,
    blockedIps,
    auditEvents,
  ] = await Promise.all([
    supabase
      .from('security_events')
      .select('count(*)')
      .eq('type', 'failed_login')
      .gte('created_at', getTimeRangeStart(timeRange)),
    
    supabase
      .from('security_events')
      .select('count(*)')
      .eq('type', 'suspicious_access')
      .gte('created_at', getTimeRangeStart(timeRange)),
    
    supabase
      .from('blocked_ips')
      .select('count(*)')
      .eq('is_active', true),
    
    supabase
      .from('audit_logs')
      .select('action, count(*)')
      .gte('created_at', getTimeRangeStart(timeRange))
      .group('action'),
  ]);
  
  return {
    failedLogins: failedLogins.data?.[0]?.count || 0,
    suspiciousActivities: suspiciousActivities.data?.[0]?.count || 0,
    blockedIps: blockedIps.data?.[0]?.count || 0,
    auditEvents: auditEvents.data || [],
    generatedAt: new Date().toISOString(),
  };
}

Incident Response

Automated Response Actions

// lib/security/incident-response.ts
export async function handleSecurityIncident(incident: SecurityEvent): Promise<void> {
  switch (incident.severity) {
    case 'critical':
      await executeCriticalResponse(incident);
      break;
    case 'high':
      await executeHighSeverityResponse(incident);
      break;
    case 'medium':
      await executeMediumSeverityResponse(incident);
      break;
    case 'low':
      await logIncident(incident);
      break;
  }
}

async function executeCriticalResponse(incident: SecurityEvent): Promise<void> {
  // Immediate actions for critical incidents
  await Promise.all([
    // Alert all administrators immediately
    alertAdministrators(incident),
    
    // Block source IP if applicable
    incident.ipAddress && await blockIpAddress(incident.ipAddress),
    
    // Disable affected user account if applicable
    incident.userId && await disableUserAccount(incident.userId, 'security_incident'),
    
    // Log to external security service
    logToSecurityService(incident),
    
    // Trigger incident response workflow
    triggerIncidentWorkflow(incident),
  ]);
}

Security Monitoring Best Practices

Monitoring Checklist

  • All authentication attempts logged
  • Failed login attempts monitored and alerted
  • Unusual access patterns detected
  • Rate limiting implemented on all endpoints
  • Security headers properly configured
  • Real-time monitoring dashboard available
  • Incident response procedures documented
  • Regular security metrics reviewed

Alert Configuration

  • Critical: Immediate notification (SMS, email, Slack)
  • High: Notification within 15 minutes
  • Medium: Daily digest report
  • Low: Weekly summary report

This monitoring and auditing system provides comprehensive security oversight while enabling rapid response to potential threats and security incidents.