/ src / lib / a2a / auth.ts
auth.ts
 1  import { validateAccessKey } from '@/lib/server/storage-auth'
 2  
 3  export interface A2AAuthResult {
 4    valid: boolean
 5    agentId: string | null
 6    error?: string
 7  }
 8  
 9  /**
10   * Validate an inbound A2A request using the SwarmClaw access key.
11   * Checks `Authorization: Bearer <key>` or `x-a2a-access-key` header.
12   */
13  export function validateA2ARequest(req: Request): A2AAuthResult {
14    const authHeader = req.headers.get('authorization')
15    const a2aKeyHeader = req.headers.get('x-a2a-access-key')
16  
17    let key: string | null = null
18    if (authHeader?.startsWith('Bearer ')) {
19      key = authHeader.slice(7)
20    } else if (a2aKeyHeader) {
21      key = a2aKeyHeader
22    }
23  
24    if (!key) {
25      return { valid: false, agentId: null, error: 'Missing authentication — provide Authorization: Bearer <key> or x-a2a-access-key header' }
26    }
27  
28    if (!validateAccessKey(key)) {
29      return { valid: false, agentId: null, error: 'Invalid access key' }
30    }
31  
32    const agentId = req.headers.get('x-a2a-agent-id')
33    return { valid: true, agentId }
34  }
35  
36  /**
37   * Extract A2A-specific headers from an inbound request.
38   */
39  export function extractA2AHeaders(req: Request): { targetAgentId: string | null; requesterAgentId: string | null } {
40    return {
41      targetAgentId: req.headers.get('x-a2a-target-agent-id'),
42      requesterAgentId: req.headers.get('x-a2a-agent-id'),
43    }
44  }
45  
46  /**
47   * Build auth headers for outbound A2A requests to remote agents.
48   */
49  export function buildA2AAuthHeaders(accessKey: string): Record<string, string> {
50    return {
51      'Content-Type': 'application/json',
52      'Authorization': `Bearer ${accessKey}`,
53    }
54  }