Express.js middleware

Express.js middleware for agent authorization (wallet or JWS/JWT)

Middleware that accepts either x-agent-wallet (Path 1) or Authorization: Bearer <token> (Path 2). ProofPack supports both JWS and JWT; standard Bearer token handling applies.

Implementation note: The wallet-only path uses ProofPack’s IsDelegateAttestationVerifier from @zipwire/proofpack-ethereum; the full-proof path uses AttestedMerkleExchangeReader and a verification context from @zipwire/proofpack. For the exact verifier config and context setup, see the Path 1 example and the ProofPack repoarrow-up-right.

import express from 'express';
import { IsDelegateAttestationVerifier } from '@zipwire/proofpack-ethereum';
import { AttestedMerkleExchangeReader } from '@zipwire/proofpack';

const app = express();

// Verifier: use full config (delegationSchemaUid, acceptedRoots, etc.) — see Path 1 and ProofPack repo
const verifier = new IsDelegateAttestationVerifier({ chains: ['base-sepolia', 'base'] }, config);
const reader = new AttestedMerkleExchangeReader();

// Middleware: Verify agent authorization
app.use(async (req, res, next) => {
  const agentWallet = req.headers['x-agent-wallet'];
  const authHeader = req.headers['authorization'];

  if (!agentWallet && !authHeader) {
    return res.status(400).json({ error: 'Agent wallet or JWS/JWT required' });
  }

  try {
    if (authHeader?.startsWith('Bearer ')) {
      // Full proof path
      const token = authHeader.slice(7);
      const result = await reader.readAsync(token, verificationContext);

      if (!result.isValid) {
        return res.status(403).json({ error: 'Invalid authorization proof' });
      }

      req.agent = {
        wallet: result.agentWallet,
        claims: result.document.merkleTree.leaves,
        verified: true
      };
    } else if (agentWallet) {
      // Wallet-only check (returns AttestationResult with .isValid)
      const result = await verifier.verifyByWallet(agentWallet);

      if (!result.isValid) {
        return res.status(403).json({ error: 'Agent not authorized by human' });
      }

      req.agent = {
        wallet: agentWallet,
        verified: true
      };
    }

    next();
  } catch (err) {
    res.status(500).json({ error: 'Verification failed', details: err.message });
  }
});

// Your API endpoints now have req.agent with verified authorization
app.post('/api/time-tracking/log', (req, res) => {
  console.log(`Agent ${req.agent.wallet} logging time`);
  // Process request
});

app.get('/api/payments/status', (req, res) => {
  if (!req.agent.claims?.verifiedHuman) {
    return res.status(403).json({ error: 'Payment queries require human verification' });
  }
  // Return payment status
});

Configure config (verifier) and verificationContext (reader) per the ProofPack repoarrow-up-right and Path 1 / Quick setup. Full guide: ProofPack & Agent Delegation.

Last updated