Native library reference. Extended CLI examples use
jacs-compat. This source reference can include unreleased changes; see the package guide for installation and MCP profiles for available tools.
Koa Middleware
Source and published packages: Version 0.16.1 has a recorded release inventory. Version 0.16.0 is the first release whose source includes the native PQ DID/JWK and Agent Card behavior. See the identity integration guide.
Sign it. Prove it. -- in your Koa app.
JACS provides jacsKoaMiddleware for Koa with the same design as the Express middleware -- verify incoming signed bodies, optionally auto-sign responses.
Quick Start
import Koa from 'koa';
import bodyParser from 'koa-bodyparser';
import { JacsClient } from '@hai.ai/jacs/client';
import { jacsKoaMiddleware } from '@hai.ai/jacs/koa';
const client = await JacsClient.quickstart({
name: 'my-agent',
domain: 'my-agent.example.com',
});
const app = new Koa();
app.use(bodyParser({ enableTypes: ['text'] }));
app.use(jacsKoaMiddleware({ client, verify: true }));
app.use(async (ctx) => {
console.log(ctx.state.jacsPayload); // verified payload
ctx.body = { status: 'ok' };
});
app.listen(3000);
Options
interface JacsKoaMiddlewareOptions {
client?: JacsClient; // Pre-initialized client (preferred)
configPath?: string; // Path to jacs.config.json (if no client)
sign?: boolean; // Auto-sign ctx.body after next() (default: false)
verify?: boolean; // Verify incoming POST/PUT/PATCH bodies (default: true)
optional?: boolean; // Allow unsigned/invalid bodies through (default: false)
authReplay?: boolean | { // Signed-body freshness/deduplication (default: false)
enabled?: boolean;
maxAgeSeconds?: number; // default: 30
clockSkewSeconds?: number; // default: 5
cacheTtlSeconds?: number; // default: maxAge + skew
};
}
How It Works
Every request gets ctx.state.jacsClient for manual use.
POST/PUT/PATCH with verify: true: A supplied body is verified. On success, ctx.state.jacsPayload is set. On failure, 401 is returned (unless optional: true).
With sign: true: After downstream middleware runs, if ctx.body is defined and not a Buffer, it is signed (including JSON scalars) before the response is sent.
Signed-body replay checks
This option adds freshness and deduplication to signed bodies. It does not authorize a route or bind the HTTP method, URL, body bytes, and audience. Use request-bound authorization and a configured signer policy for that boundary:
app.use(
jacsKoaMiddleware({
client,
verify: true,
authReplay: { enabled: true, maxAgeSeconds: 30, clockSkewSeconds: 5 },
})
);
When enabled, middleware enforces:
- signature timestamp freshness (
maxAgeSeconds+clockSkewSeconds) - single-use
(signerId, signature)dedupe inside a TTL cache
Notes:
- Keep this mode scoped to auth-style endpoints.
- Cache is in-memory per process; use a shared cache for multi-instance deployments.
Response signing fails closed by default: errors withhold the unsigned body.
The explicit allowUnsignedOutput: true compatibility option relaxes this;
strict: true overrides that option. Routes requiring a signed body should
also reject a missing payload, since body verification is not route authorization.
Auto-Sign Responses
app.use(jacsKoaMiddleware({ client, sign: true }));
app.use(async (ctx) => {
// This will be JACS-signed automatically after next()
ctx.body = { result: 42, timestamp: new Date().toISOString() };
});
Manual Signing
app.use(jacsKoaMiddleware({ client }));
app.use(async (ctx) => {
const result = processData(ctx.state.jacsPayload);
const signed = await ctx.state.jacsClient.signMessage(result);
ctx.type = 'application/json';
ctx.body = signed.raw;
});
Comparison with Express
| Feature | Express | Koa |
|---|---|---|
| Import | jacsMiddleware from @hai.ai/jacs/express | jacsKoaMiddleware from @hai.ai/jacs/koa |
| Client access | req.jacsClient | ctx.state.jacsClient |
| Payload | req.jacsPayload | ctx.state.jacsPayload |
| Auto-sign target | res.json() interception | ctx.body after next() |
Next Steps
- Express Middleware - Express version
- Vercel AI SDK - AI model provenance signing
- API Reference - Complete API documentation