UNPKG

@kya-os/agentshield-nextjs

Version:

Next.js middleware for AgentShield AI agent detection

176 lines (174 loc) 5.27 kB
'use strict'; // src/session-tracker.ts var EdgeSessionTracker = class { config; constructor(config) { this.config = { enabled: config.enabled, cookieName: config.cookieName || "__agentshield_session", cookieMaxAge: config.cookieMaxAge || 3600, // 1 hour default encryptionKey: config.encryptionKey || process.env.AGENTSHIELD_SECRET || "agentshield-default-key" }; } /** * Track a new AI agent session */ async track(_request, response, result) { try { if (!this.config.enabled || !result.isAgent) { return response; } const sessionData = { id: crypto.randomUUID(), agent: result.detectedAgent?.name || "unknown", confidence: result.confidence, detectedAt: Date.now(), expires: Date.now() + this.config.cookieMaxAge * 1e3 }; const encrypted = await this.encrypt(JSON.stringify(sessionData)); response.cookies.set(this.config.cookieName, encrypted, { httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "lax", maxAge: this.config.cookieMaxAge, path: "/" }); return response; } catch (error) { if (process.env.DEBUG_AGENTSHIELD) { console.warn("AgentShield: Failed to track session:", error); } return response; } } /** * Check for existing AI agent session */ async check(request) { try { if (!this.config.enabled) { return null; } const cookie = request.cookies.get(this.config.cookieName); if (!cookie?.value) { return null; } const decrypted = await this.decrypt(cookie.value); const session = JSON.parse(decrypted); if (session.expires < Date.now()) { return null; } return session; } catch (error) { if (process.env.DEBUG_AGENTSHIELD) { console.warn("AgentShield: Failed to check session:", error); } return null; } } /** * Clear an existing session */ clear(response) { try { response.cookies.delete(this.config.cookieName); } catch (error) { if (process.env.DEBUG_AGENTSHIELD) { console.warn("AgentShield: Failed to clear session:", error); } } return response; } /** * Simple encryption using Web Crypto API (Edge-compatible) */ async encrypt(data) { try { const key = this.config.encryptionKey; const encoded = new TextEncoder().encode(data); const obfuscated = new Uint8Array(encoded.length); for (let i = 0; i < encoded.length; i++) { obfuscated[i] = (encoded[i] || 0) ^ key.charCodeAt(i % key.length); } return btoa( Array.from(obfuscated, (byte) => String.fromCharCode(byte)).join("") ); } catch (error) { return btoa(data); } } /** * Simple decryption (Edge-compatible) */ async decrypt(data) { try { const key = this.config.encryptionKey; const decoded = Uint8Array.from(atob(data), (c) => c.charCodeAt(0)); const deobfuscated = new Uint8Array(decoded.length); for (let i = 0; i < decoded.length; i++) { deobfuscated[i] = (decoded[i] || 0) ^ key.charCodeAt(i % key.length); } return new TextDecoder().decode(deobfuscated); } catch (error) { return atob(data); } } }; var StatelessSessionChecker = class { static check(headers) { try { const agent = headers["x-agentshield-session-agent"]; const confidence = headers["x-agentshield-session-confidence"]; const sessionId = headers["x-agentshield-session-id"]; if (agent && confidence && sessionId) { return { id: sessionId, agent, confidence: parseFloat(confidence), detectedAt: Date.now(), expires: Date.now() + 36e5 // 1 hour }; } const cookieHeader = headers["cookie"]; if (cookieHeader && cookieHeader.includes("__agentshield_session=")) { const match = cookieHeader.match(/__agentshield_session=([^;]+)/); if (match && match[1]) { try { const decoded = atob(match[1]); return JSON.parse(decoded); } catch { } } } return null; } catch { return null; } } static setHeaders(response, session) { try { if (response.setHeader) { response.setHeader("X-AgentShield-Session-Agent", session.agent); response.setHeader( "X-AgentShield-Session-Confidence", session.confidence.toString() ); response.setHeader("X-AgentShield-Session-Id", session.id); } else if (response.headers && response.headers.set) { response.headers.set("x-agentshield-session-agent", session.agent); response.headers.set( "x-agentshield-session-confidence", session.confidence.toString() ); response.headers.set("x-agentshield-session-id", session.id); } } catch { } } }; exports.EdgeSessionTracker = EdgeSessionTracker; exports.StatelessSessionChecker = StatelessSessionChecker; //# sourceMappingURL=session-tracker.js.map //# sourceMappingURL=session-tracker.js.map