The library supports server signatures and integration with ALTCHA Sentinel. To process verifications generated by Sentinel, configure the HMAC secret using the API key’s secret value. The verification result will include verificationData returned by Sentinel.
const HMAC_SECRET = 'sec_...'; // Use the API key's secret value
const altcha = create({
// ...
hmacSignatureSecret: HMAC_SECRET,
});- Do not use the
/challengeendpoint. Challenges are generated by the Sentinel server. - Your server only verifies ALTCHA payloads created by Sentinel.
For more details about the differences between self-contained and Sentinel verification, see the documentation: https://altcha.org/docs/v2/server-verification/
Instead of verifying the HMAC signature locally, you can call Sentinel's /v1/verify/signature API directly with verifyServer. This avoids managing the HMAC secret in your server, at the cost of a network round-trip:
import { verifyServer } from 'altcha-lib';
const result = await verifyServer({
payload, // the payload received from POST /v1/verify
url: 'https://sentinel.example.com/v1/verify/signature',
secret: API_KEY_SECRET, // optional, checked against the payload's API key
timeout: 10_000,
retries: 2,
});
if (result.verified) {
// ...
}All framework plugins (Express, Fastify, NestJS, Next.js, Nuxt/H3, SvelteKit, Hono) accept
a verifyServer option. When set, payloads submitted through middleware (or SvelteKit's
createHandle/verifyEvent) are verified remotely via verifyServer instead of locally, so
you don't need to configure hmacSignatureSecret at all:
const altcha = create({
verifyServer: {
url: 'https://sentinel.example.com/v1/verify/signature',
secret: API_KEY_SECRET, // optional
timeout: 10_000,
retries: 2,
},
});deriveKey and createChallengeParameters are also optional — they're only needed for
challengeHandler and for verifying self-hosted (non-Sentinel) payloads. If you're relying
entirely on Sentinel to issue and sign challenges, omit all three and don't wire up
challengeHandler.
Note: verifyHandler (the standalone /verify endpoint intended for custom, external
integrations — see /docs/verify-route.md) never uses verifyServer,
even when it's configured. It only verifies payloads locally. If a custom integration needs
remote Sentinel verification, call the exported verifyServer() function directly instead of
going through the plugin's /verify route.