UNPKG

@kya-os/agentshield-nextjs

Version:

Next.js middleware for AgentShield AI agent detection

381 lines (291 loc) 8.65 kB
# @kya-os/agentshield-nextjs Next.js middleware and React hooks for AgentShield AI agent detection and protection. ## Features - 🚀 **Next.js Middleware**: Edge-compatible middleware for all routes - ⚛️ **React Hooks**: Client-side detection and monitoring - 🎯 **Flexible Actions**: Block, redirect, rewrite, or log detected agents - 🛡️ **Edge Runtime**: Optimized for Vercel Edge Functions - 📊 **Built-in Analytics**: Track detection patterns and statistics ## Installation ```bash npm install @kya-os/agentshield-nextjs ``` ## Quick Start ### Middleware Setup Create `middleware.js` (or `middleware.ts`) in your project root: ```javascript import { agentShield } from '@kya-os/agentshield-nextjs'; export default agentShield({ onAgentDetected: 'block', confidenceThreshold: 0.8, // NEW: Session tracking (v0.1.27+) sessionTracking: { enabled: true, // Track continued sessions from AI agents }, }); export const config = { matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'], }; ``` ### React Hooks ```javascript 'use client'; import { useAgentDetection } from '@kya-os/agentshield-nextjs'; export default function SecurityMonitor() { const { detect, isDetecting, lastResult } = useAgentDetection({ confidenceThreshold: 0.7, }); const handleCheck = async () => { const result = await detect(); if (result.isAgent) { alert('Agent detected!'); } }; return ( <div> <button onClick={handleCheck} disabled={isDetecting}> {isDetecting ? 'Checking...' : 'Check for Agents'} </button> {lastResult && ( <div> <p>Is Agent: {lastResult.isAgent ? 'Yes' : 'No'}</p> <p>Confidence: {(lastResult.confidence * 100).toFixed(1)}%</p> </div> )} </div> ); } ``` ## Middleware Configuration ```javascript import { agentShield } from '@kya-os/agentshield-nextjs'; export default agentShield({ // Core detection options confidenceThreshold: 0.7, enablePatternMatching: true, enableBehaviorAnalysis: true, // Action when agent is detected onAgentDetected: 'block', // 'block' | 'redirect' | 'rewrite' | 'allow' | 'log' // Skip detection for paths skipPaths: ['/api/webhooks', /^\/admin/], // Custom responses blockedResponse: { status: 403, message: 'Access denied', }, redirectUrl: '/blocked', rewriteUrl: '/blocked', // Custom handler onDetection: async (request, result) => { console.log('Agent detected:', result); // Return custom NextResponse or void }, }); ``` ## Actions ### Block Agents ```javascript export default agentShield({ onAgentDetected: 'block', blockedResponse: { status: 403, message: 'Automated access not allowed', headers: { 'Content-Type': 'application/json', 'X-Robots-Tag': 'noindex', }, }, }); ``` ### Redirect Agents ```javascript export default agentShield({ onAgentDetected: 'redirect', redirectUrl: '/blocked', confidenceThreshold: 0.8, }); ``` ### Rewrite Requests ```javascript export default agentShield({ onAgentDetected: 'rewrite', rewriteUrl: '/bot-content', confidenceThreshold: 0.6, }); ``` ### Custom Logic ```javascript export default agentShield({ onDetection: async (request, result) => { if (result.confidence > 0.9) { // High confidence - block return NextResponse.json({ error: 'Blocked' }, { status: 403 }); } else if (result.confidence > 0.5) { // Medium confidence - redirect to captcha return NextResponse.redirect(new URL('/verify', request.url)); } // Low confidence - continue }, }); ``` ## React Hooks ### useAgentDetection Client-side agent detection: ```javascript import { useAgentDetection } from '@kya-os/agentshield-nextjs'; function SecurityComponent() { const { detect, isDetecting, lastResult, detector } = useAgentDetection({ confidenceThreshold: 0.7, }); useEffect(() => { // Auto-detect on component mount detect(); }, [detect]); return ( <div> {lastResult?.isAgent && ( <div className='alert'>Agent detected with {lastResult.confidence} confidence</div> )} </div> ); } ``` ### useDetectionMonitor Monitor and track detection events: ```javascript import { useDetectionMonitor } from '@kya-os/agentshield-nextjs'; function AnalyticsDashboard() { const { detectionHistory, getStats, clearHistory } = useDetectionMonitor(context => { // Handle each detection console.log('Detection event:', context); }); const stats = getStats(); return ( <div> <h2>Detection Statistics</h2> <p>Total Requests: {stats.total}</p> <p>Agents Detected: {stats.detected}</p> <p>Detection Rate: {(stats.detectionRate * 100).toFixed(1)}%</p> <p>Average Confidence: {(stats.avgConfidence * 100).toFixed(1)}%</p> <button onClick={clearHistory}>Clear History</button> </div> ); } ``` ## API Routes Integration Protect API routes with server-side detection: ```javascript // pages/api/protected.js or app/api/protected/route.js import { AgentDetector } from '@kya-os/agentshield'; const detector = new AgentDetector(); export async function GET(request) { const context = { userAgent: request.headers.get('user-agent'), ip: request.ip, headers: Object.fromEntries(request.headers.entries()), }; const result = await detector.analyze(context); if (result.isAgent && result.confidence > 0.7) { return NextResponse.json({ error: 'Automated access detected' }, { status: 403 }); } return NextResponse.json({ data: 'Protected content' }); } ``` ## Advanced Usage ### Path-Specific Configuration ```javascript import { NextRequest, NextResponse } from 'next/server'; import { AgentDetector } from '@kya-os/agentshield'; const detector = new AgentDetector(); export async function middleware(request: NextRequest) { const { pathname } = request.nextUrl; // Different thresholds for different paths let threshold = 0.7; if (pathname.startsWith('/api/')) { threshold = 0.5; // More sensitive for API } else if (pathname.startsWith('/admin/')) { threshold = 0.9; // Less sensitive for admin (humans expected) } const context = { userAgent: request.headers.get('user-agent') ?? undefined, ip: request.ip, headers: Object.fromEntries(request.headers.entries()), url: request.url, }; const result = await detector.analyze(context); if (result.isAgent && result.confidence >= threshold) { return NextResponse.json( { error: 'Access denied' }, { status: 403 } ); } return NextResponse.next(); } ``` ### Server Components Use detection results in Server Components: ```javascript // app/dashboard/page.tsx import { headers } from 'next/headers'; import { AgentDetector } from '@kya-os/agentshield'; export default async function Dashboard() { const headersList = headers(); const detector = new AgentDetector(); const result = await detector.analyze({ userAgent: headersList.get('user-agent') ?? undefined, headers: Object.fromEntries(headersList.entries()), }); if (result.isAgent) { return <div>Automated access detected</div>; } return <div>Welcome to the dashboard!</div>; } ``` ## TypeScript Support Full TypeScript support with proper types: ```typescript import { NextRequest } from 'next/server'; import { agentShield, NextJSMiddlewareConfig } from '@kya-os/agentshield-nextjs'; const config: NextJSMiddlewareConfig = { onAgentDetected: 'block', confidenceThreshold: 0.8, onDetection: async (request: NextRequest, result) => { // Fully typed parameters console.log(result.confidence); }, }; export default agentShield(config); ``` ## Examples ### E-commerce Protection ```javascript // Protect product pages from scrapers export default agentShield({ onAgentDetected: 'redirect', redirectUrl: '/captcha', confidenceThreshold: 0.6, skipPaths: ['/api/webhooks', '/health'], }); export const config = { matcher: ['/products/:path*', '/search/:path*'], }; ``` ### Content Publishing ```javascript // Allow search engines, block other bots export default agentShield({ onDetection: async (request, result) => { const userAgent = request.headers.get('user-agent') || ''; // Allow known search engines if (/googlebot|bingbot|slurp/i.test(userAgent)) { return; // Continue } // Block other agents if (result.isAgent && result.confidence > 0.5) { return NextResponse.json({ error: 'Bot access restricted' }, { status: 403 }); } }, }); ``` ## License MIT OR Apache-2.0