ALTCHA Spam Protection: Challenge Endpoint
Challenge endpoint of the ALTCHA Spam Protection module for OXID 7: request, JSON response, HTTP status codes, rate limit, structure of the solution in the POST field altcha and the server-side verification.
ALTCHA Spam Protection: Challenge Endpoint
Live Demo: Try this and other plugins live — no installation, no risk: demo.markus-michalski.net
The module provides a single endpoint: the controller mmd_altcha_challenge, which creates a new challenge for the widget. The widget calls it automatically; you only need to call it yourself if you replace the widget.
Request
GET index.php?cl=mmd_altcha_challenge&fnc=getChallenge
The full URL is returned by oViewConf.getAltchaChallengeUrl() (see Storefront). The response is always JSON with the headers Content-Type: application/json; charset=utf-8 and Cache-Control: no-store, no-cache, must-revalidate.
Response
{
"algorithm": "SHA-256",
"challenge": "9f2c...",
"salt": "a1b2c3d4e5f6a1b2c3d4e5f6.1760000000",
"signature": "7d3e...",
"maxnumber": 50000
}
| Field | Content |
|---|---|
algorithm |
Always SHA-256 |
challenge |
SHA-256 hash of salt and a secret random number between 1 and maxnumber |
salt |
24 random hex characters, a dot and the Unix timestamp of creation |
signature |
HMAC-SHA256 of the challenge using the module's HMAC secret |
maxnumber |
Value of the setting "Maximum number (difficulty)" |
The server does not store issued challenges. Only a solved and verified challenge is stored (protection against reuse).
Status codes
| Status | Meaning | Response body |
|---|---|---|
| 200 | Challenge created | Challenge JSON (see above) |
| 503 | Spam protection or ALTCHA is switched off | {"error":"ALTCHA is disabled"} |
| 429 | Endpoint rate limit exceeded, the Retry-After header contains the seconds |
{"error":"Too many requests"} |
| 500 | Internal error | {"error":"Challenge generation failed"} in productive mode, otherwise the exception message |
The endpoint rate limit is counted per client address, can be switched with "Challenge endpoint rate limit" and defaults to 30 requests in 60 seconds (see Configuration). The time window is rounded up to whole minutes internally. Only allowed requests are counted. The value in Retry-After is the configured time window in seconds.
Solution on submit
The widget solves the challenge in the browser and sends the result in the POST field altcha. The value is a Base64-encoded JSON with the fields algorithm, challenge, number, salt and signature. The server reads only this field, there is no header variant.
Verification runs in this order and rejects at the first failure:
- The field
altchais present, valid Base64 and valid JSON containing all five fields. algorithmisSHA-256.signaturematches the HMAC of thechallenge.- The timestamp in
saltis not older than "Challenge validity (seconds)". - The SHA-256 hash of
saltandnumberequals thechallenge. - The
challengehas never been used before. It is recorded as used at this point, even if rate limiting rejects the submission afterwards.
Client address
Rate limiting uses the first entry of the X-Forwarded-For header, otherwise REMOTE_ADDR. More on the Privacy page.