Skip to content

Challenges

crate.auth.challenges holds the human-verification challenges you can put in front of registration, password reset, or any other endpoint that attracts bots. Every implementation satisfies one interface, so swapping providers is a constructor change.

interface IChallenge {
string generate(HTTPServerRequest req, HTTPServerResponse res);
string getTemplate(string challengeLocation);
Json getConfig();
bool validate(string response);
}
MethodReturns
generateA challenge for a request that came from the challenge template; empty for provider-hosted challenges
getTemplateHTML to embed in a server-rendered form
getConfigThe public configuration a JavaScript client needs (site key and friends)
validateWhether the client’s response is accepted

CodeEntry — a SysTime time and a string result — is the shape used to hold a pending secret code.

ClassModuleVerification
ReCaptchacrate.auth.challenges.recaptchaGoogle reCAPTCHA v3, server-side siteverify call
MtCaptchacrate.auth.challenges.mtcaptchamtCAPTCHA checktoken call
ALTCHAcrate.auth.challenges.altchaSelf-hosted proof of work — see ALTCHA

ALTCHA is a set of free functions rather than an IChallenge class; it needs no third-party service.

import crate.auth.challenges.recaptcha;
class MyReCaptchaConfig : IReCaptchaConfig {
string siteKey() { return "6Lc..."; }
string secretKey() { return "6Lc..."; }
}
auto challenge = new ReCaptcha(new MyReCaptchaConfig());

getTemplate returns a script block that runs grecaptcha.execute with the login action and writes the token into a hidden response input. getConfig returns {"siteKey": "..."}. generate returns an empty string — reCAPTCHA issues its own challenge client-side.

import crate.auth.challenges.mtcaptcha;
class MyMtCaptchaConfig : IMtCaptchaConfig {
string siteKey() { return "MTPublic-..."; }
string privateKey() { return "MTPrivate-..."; }
}
auto challenge = new MtCaptcha(new MyMtCaptchaConfig());

getConfig returns {"siteKey": "..."}. getTemplate and generate both return an empty string; render the widget from the site key on the client.

Both hosted implementations fail open. validate returns false when the provider answers without a success field, and false when success is false — but if the HTTP call itself throws (the provider is unreachable, DNS fails, the response is not JSON), the error is logged and validate returns true. A challenge is therefore an obstacle to bots, not a gate you can rely on while the provider is down. Pair it with the spam prevention helpers, which do not depend on a third party.