# SvelteKit The SvelteKit plugin simplifies integrating ALTCHA into your application. It provides handlers 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 `event.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. ## Usage ### 1. Create the altcha instance File: `src/lib/altcha.ts` ```ts import { create, deriveHmacKeySecret, randomInt, CappedMap } from 'altcha-lib/frameworks/sveltekit'; import { deriveKey } from 'altcha-lib/algorithms/pbkdf2'; // Define your HMAC secret const HMAC_SECRET = 'secret.key'; export 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. Challenge endpoint File: `src/routes/altcha/challenge/+server.ts` ```ts import { altcha } from '$lib/altcha'; export const GET = altcha.challengeHandler; ``` ### 3. Standalone verify endpoint File: `src/routes/altcha/verify/+server.ts` ```ts import { altcha } from '$lib/altcha'; export const POST = altcha.verifyHandler; ``` ### 4a. Protect a route handler with verifyEvent File: `src/routes/submit/+page.server.ts` ```ts import { altcha } from '$lib/altcha'; import { fail } from '@sveltejs/kit'; import type { Actions } from './$types'; export const actions = { default: async (event) => { const result = await altcha.verifyEvent(event); if (result.error) { return fail(403, { error: 'Verification failed' }); } // Process the form... }, } satisfies Actions; ``` ### 4b. Use middleware via hooks File: `src/hooks.server.ts` ```ts import { sequence } from '@sveltejs/kit/hooks'; import { altcha } from '$lib/altcha'; const altchaGuard = altcha.createHandle({ throwOnFailure: true }); // Apply only to protected routes: const protectedAltcha: Handle = async ({ event, resolve }) => { if (event.url.pathname.startsWith('/api/protected')) { return altchaGuard({ event, resolve }); } return resolve(event); }; export const handle = sequence(protectedAltcha); ```