UNPKG

anon-identity

Version:

Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure

196 lines 6.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SessionManager = void 0; const crypto_1 = require("crypto"); class SessionManager { constructor(options = {}) { this.sessions = new Map(); this.credentialToSessions = new Map(); this.options = { defaultSessionDuration: options.defaultSessionDuration || 3600000, // 1 hour maxSessionDuration: options.maxSessionDuration || 86400000, // 24 hours cleanupInterval: options.cleanupInterval || 300000 // 5 minutes }; // Start cleanup timer this.startCleanupTimer(); } /** * Create a new session from a verification result */ async createSession(verificationResult, metadata) { if (!verificationResult.valid || !verificationResult.holder || !verificationResult.credentials) { throw new Error('Cannot create session from invalid verification result'); } const sessionId = this.generateSessionId(); const now = new Date(); const expiresAt = new Date(now.getTime() + this.options.defaultSessionDuration); // Aggregate all attributes from verified credentials const allAttributes = {}; const credentialIds = []; for (const credential of verificationResult.credentials) { credentialIds.push(credential.id); Object.assign(allAttributes, credential.attributes); } const session = { id: sessionId, holderDID: verificationResult.holder, credentialIds, attributes: allAttributes, createdAt: now, expiresAt, lastAccessedAt: now, metadata }; // Store session this.sessions.set(sessionId, session); // Map credentials to sessions for revocation handling for (const credentialId of credentialIds) { if (!this.credentialToSessions.has(credentialId)) { this.credentialToSessions.set(credentialId, new Set()); } this.credentialToSessions.get(credentialId).add(sessionId); } return session; } /** * Validate an existing session */ async validateSession(sessionId) { const session = this.sessions.get(sessionId); if (!session) { return { valid: false, reason: 'Session not found' }; } const now = new Date(); // Check if session has expired if (now > session.expiresAt) { this.removeSession(sessionId); return { valid: false, reason: 'Session expired' }; } // Update last accessed time session.lastAccessedAt = now; return { valid: true, session }; } /** * Revoke all sessions associated with a credential */ async revokeSessions(credentialId) { const sessionIds = this.credentialToSessions.get(credentialId); if (!sessionIds) { return; } // Remove all associated sessions for (const sessionId of sessionIds) { this.removeSession(sessionId); } // Clean up the credential mapping this.credentialToSessions.delete(credentialId); } /** * Set or update session expiry */ async setSessionExpiry(sessionId, duration) { const session = this.sessions.get(sessionId); if (!session) { throw new Error('Session not found'); } // Enforce maximum session duration const maxDuration = Math.min(duration, this.options.maxSessionDuration); const now = new Date(); session.expiresAt = new Date(now.getTime() + maxDuration); } /** * Get session by ID */ getSession(sessionId) { return this.sessions.get(sessionId); } /** * Get all active sessions */ getAllSessions() { return Array.from(this.sessions.values()); } /** * Get sessions by holder DID */ getSessionsByHolder(holderDID) { return Array.from(this.sessions.values()).filter(session => session.holderDID === holderDID); } /** * Manually remove a session */ removeSession(sessionId) { const session = this.sessions.get(sessionId); if (!session) { return; } // Remove from main storage this.sessions.delete(sessionId); // Remove from credential mappings for (const credentialId of session.credentialIds) { const sessions = this.credentialToSessions.get(credentialId); if (sessions) { sessions.delete(sessionId); if (sessions.size === 0) { this.credentialToSessions.delete(credentialId); } } } } /** * Clear all sessions */ clearAllSessions() { this.sessions.clear(); this.credentialToSessions.clear(); } /** * Stop the cleanup timer */ destroy() { if (this.cleanupTimer) { clearInterval(this.cleanupTimer); this.cleanupTimer = undefined; } } /** * Generate a secure session ID */ generateSessionId() { return (0, crypto_1.randomBytes)(32).toString('base64url'); } /** * Start the cleanup timer to remove expired sessions */ startCleanupTimer() { this.cleanupTimer = setInterval(() => { this.cleanupExpiredSessions(); }, this.options.cleanupInterval); } /** * Clean up expired sessions */ cleanupExpiredSessions() { const now = new Date(); const expiredSessionIds = []; for (const [sessionId, session] of this.sessions) { if (now > session.expiresAt) { expiredSessionIds.push(sessionId); } } for (const sessionId of expiredSessionIds) { this.removeSession(sessionId); } } } exports.SessionManager = SessionManager; //# sourceMappingURL=session-manager.js.map