UNPKG

@kya-os/mcp-i

Version:

The TypeScript MCP framework with identity features built-in

145 lines (144 loc) 5.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DelegationMiddleware = exports.DefaultDelegationHooks = void 0; exports.createDelegationHooks = createDelegationHooks; exports.createDelegationMiddleware = createDelegationMiddleware; /** * Default delegation hooks implementation */ class DefaultDelegationHooks { delegationManager; options; constructor(delegationManager, options = {}) { this.delegationManager = delegationManager; this.options = options; } async beforeProof(meta) { // Resolve delegation reference if needed if (!meta.delegationRef && this.options.autoResolveDelegation) { const context = { audience: meta.audience, sessionId: meta.sessionId, did: meta.did, kid: meta.kid, scopes: meta.scopeId ? [meta.scopeId] : undefined, }; meta.delegationRef = await this.resolveDelegation(context); } return meta; } async afterProof(meta) { // Validate delegation if present if (meta.delegationRef) { const isActive = await this.delegationManager.isActive(meta.delegationRef); if (!isActive) { throw new Error(`Delegation ${meta.delegationRef} is not active or has been revoked`); } // Check delegation expiry const delegation = await this.delegationManager.get(meta.delegationRef); if (delegation) { const now = Math.floor(Date.now() / 1000); if (delegation.exp < now) { throw new Error(`Delegation ${meta.delegationRef} has expired`); } // Validate scopes if specified if (meta.scopeId && !delegation.scopes.includes(meta.scopeId)) { throw new Error(`Scope ${meta.scopeId} not authorized by delegation ${meta.delegationRef}`); } // Validate audience if specified if (delegation.aud && delegation.aud !== meta.audience) { throw new Error(`Audience ${meta.audience} not authorized by delegation ${meta.delegationRef}`); } } } } async resolveDelegation(context) { // Implement delegation resolution logic to reuse existing chains try { // 1. Look up active delegations for the DID (subject) const delegations = await this.delegationManager.listBySubject(context.did); if (!delegations || delegations.length === 0) { return undefined; } // 2. Filter by audience and scopes // We want to find a delegation that satisfies ALL required scopes and matches the audience const validDelegation = delegations.find((d) => { // Check audience if context specifies one if (context.audience && d.aud && d.aud !== context.audience) { return false; } // Check scopes if context specifies them if (context.scopes && context.scopes.length > 0) { const hasAllScopes = context.scopes.every((scope) => d.scopes.includes(scope)); if (!hasAllScopes) return false; } // Check expiry (redundant with isActive check but good for safety) const now = Math.floor(Date.now() / 1000); if (d.exp < now) return false; if (d.nbf && d.nbf > now) return false; return true; }); // 3. Return the best match return validDelegation?.delegationRef; } catch (error) { console.warn("Failed to resolve delegation:", error); return undefined; } } } exports.DefaultDelegationHooks = DefaultDelegationHooks; /** * Create delegation hooks instance */ function createDelegationHooks(delegationManager, options) { return new DefaultDelegationHooks(delegationManager, options); } /** * Delegation middleware for runtime integration */ class DelegationMiddleware { hooks; options; constructor(hooks, options = {}) { this.hooks = hooks; this.options = options; } /** * Process request and attach delegation context */ async processRequest(meta, context) { // Apply before-proof hooks if (this.hooks.beforeProof) { meta = await this.hooks.beforeProof(meta); } // Resolve delegation if not already present if (!meta.delegationRef && this.hooks.resolveDelegation) { meta.delegationRef = await this.hooks.resolveDelegation(context); } return meta; } /** * Validate proof after generation */ async validateProof(meta) { // Apply after-proof hooks if (this.hooks.afterProof) { await this.hooks.afterProof(meta); } // Check if delegation is required if (this.options.requireDelegation && !meta.delegationRef) { throw new Error("Delegation is required but not present in proof"); } } } exports.DelegationMiddleware = DelegationMiddleware; /** * Create delegation middleware instance */ function createDelegationMiddleware(hooks, options) { return new DelegationMiddleware(hooks, options); }