Middleware Reference

Drop-in request verification for Next.js and Express.

Next.js

typescript
import { withAuthProof } from "@authproof/middleware/next";

export const POST = withAuthProof(config, async (request, context) => {
  const { actor } = context;
  return Response.json({ wallet: actor.address, chain: actor.chainId });
});

Express

typescript
import { expressAuthProof } from "@authproof/middleware/express";

app.post("/orders", expressAuthProof(config), (req, res) => {
  const { actor } = res.locals.authProof;
  res.json({ wallet: actor.address });
});

Framework-agnostic core

typescript
import { verifyAuthProofRequest } from "@authproof/middleware";

const result = await verifyAuthProofRequest(request, config);
if (!result.ok) {
  return new Response(result.error.message, { status: result.error.status });
}
// result.context.actor — verified actor

AuthProofConfig

PropTypeDescription
projectAuthProofProjectProject config loaded from the database via loadProject(projectId).
publicClientsRecord<number, PublicClient>Viem PublicClient instances keyed by chain ID. Used for signature verification and policy evaluation.
nonceStoreNonceStoreStore for replay protection. MemoryNonceStore for dev, RedisNonceStore for production.
rateLimitStoreRateLimitStore (optional)Store for per-wallet rate limiting. Required if rateLimit policy is configured.
usageLoggerUsageLogger (optional)Writes every request to RequestLog. Use DatabaseUsageLogger in production.

AuthProofContext

PropTypeDescription
actor.address0x${string}Verified wallet address of the signer.
actor.chainIdnumberChain ID the wallet signed on.
actor.keyIdstringCanonical key ID: erc8128:<chainId>:<address>.
actor.smartAccountbooleanTrue if the signer is a smart contract wallet (ERC-1271).
projectAuthProofProjectThe project config used for verification.

Error responses

All verification failures return a JSON body with { error, code, message }.

json
// 401 — signature invalid or expired
{ "error": "ERC-8128 verification failed: expired", "code": "expired" }

// 403 — policy rejected
{ "error": "Chain 1 is not enabled for this project.", "code": "chain_not_allowed" }

// 429 — rate limited
{ "error": "Per-wallet rate limit exceeded.", "code": "rate_limited" }