# Express The Express plugin simplifies integrating ALTCHA into your application. It provides routes and middleware for challenge generation and verification. ## Handlers * `challengeHandler` — Generates a new challenge. Configure this endpoint as the widget’s `challenge` URL. * `verifyHandler` — Optional handler for server-side verification. Useful when external services need to verify a payload. ## Middleware The middleware automatically handles verification during requests. Features: * Validates the payload from the request body or a configured cookie. * Sets `res.locals.altcha: AltchaResult`, which includes the challenge data and verification result. Options: * `throwOnFailure: boolean` — Whether to throw an error on verification failure (default: `true`). ## Store The `store` marks challenges as used to prevent reuse. See [`/docs/store.md`](/docs/store.md) for details. ## Remote verification (Sentinel) Pass a `verifyServer` option to verify Sentinel-issued payloads remotely via Sentinel's `/v1/verify/signature` API instead of locally with `hmacSignatureSecret`. See [`/docs/server-signatures.md#remote-verification-sentinel-api`](/docs/server-signatures.md#remote-verification-sentinel-api) for details. ## Example [`/examples/express-example.ts`](/examples/express-example.ts) ## Usage ### 1. Configure ALTCHA ```ts import { create, deriveHmacKeySecret, randomInt, CappedMap } from 'altcha-lib/frameworks/express'; import { deriveKey } from 'altcha-lib/algorithms/pbkdf2'; // Define your HMAC secret const HMAC_SECRET = 'secret.key'; const altcha = create({ // Verification HMAC secrets hmacSignatureSecret: HMAC_SECRET, hmacKeySignatureSecret: await deriveHmacKeySecret(HMAC_SECRET), // Adjust challenge parameters createChallengeParameters: () => { return { algorithm: 'PBKDF2/SHA-256', // Adjust cost and counter depending on the algorithm cost: 5_000, counter: randomInt(5_000, 10_000), expiresAt: new Date(Date.now() + 600_000), // 10 minutes }; }, // Key derivation function for the selected algorithm deriveKey, // Use a cookie instead of form data to send the payload setCookie: { name: 'altcha', path: '/', }, // In distributed environments, use Redis or another shared store store: new CappedMap({ maxSize: 1_000, }), }); ``` ### 2. Mount the challenge routes ```ts const app = express(); // Mount the /altcha/challenge and /altcha/verify routes app.get('/altcha/challenge', altcha.challengeHandler); app.post('/altcha/verify', altcha.verifyHandler); ``` ### 3. Protect routes with middleware ```ts // Apply ALTCHA middleware for automatic verification app.post('/submit', altcha.middleware(), (req, res) => { res.json({ altcha: res.locals.altcha, body: req.body, }); }); ```