Server Integration
PoW verification process
The verification process relies on computational work (SHA-hashing) and involves the following steps:
- User initiates verification process.
- Widget makes a request to
challengeurl
to fetch the challenge data. - Widget processes and solves the challenge based on the retrieved data.
- User submits the form containing the solved challenge.
- Server checks the payload in the form submission to ensure it matches the expected challenge solution.
The client-side aspect is managed by the ALTCHA widget, while the implementation of server-side verification is required. The server’s submission handler (e.g., POST /form_submit
) needs to authenticate the ALTCHA payload upon form submission.
Refer to the proof-of-work documentation to read more about the mechanism behind ALTCHA.
Complexity
Generating a new challenge involves three passes of SHA computation (once for the challenge and twice for the HMAC signature). Similarly, verifying a solution also requires three passes.
The range of the random number adjusts the difficulty of the computational task required from the client.
For more details, refer to adjusting complexity.
Server
The server must generate a new challenge for each ALTCHA verification. There are two methods to provide the challenge to the widget:
-
Using
challengeurl
: If configured, the widget fetches the challenge from the specified URL. The server must return a new challenge as described below. -
Using
challengejson
: Directly provide the challenge as a JSON-encoded string. This method is useful for server-rendered pages.
Read more about the proof-of-work mechanism.
Creating a Challenge
Below is a pseudo-code example for creating a challenge on the server:
When the parameter maxnumber
is returned to the client, the ALTCHA widget can better optimize the workload distribution between multiple workers, making it run faster. The official libraries return the maxnumber
value by default as it is generally recommended. Depending on your use case, the parameter maxnumber
could be considered a secret parameter, which should not be exposed to the client as it reveals the range of the number. In specific cases where you intentionally want a high difficulty, such as M2M or custom integrations, don’t return maxnumber
.
Salt Parameters
Starting from Widget version v0.4
(May 2024), it is recommended to include the expires
flag and additional parameters in the salt
as URL-encoded query strings. This allows you to pass custom data, which will be part of the signature and verifiable on the server.
The widget automatically detects the expires
parameter when provided in the salt as a Unix timestamp in seconds:
To ensure compatibility with future versions of the widget, it’s recommended to prefix any custom parameters with an underscore _
.
The altcha-lib
library already supports salt parameters and automatically verifies the expiration of the challenge from version v0.3
.
Form submission
Upon submission within a <form>
, the server will receive data encoded as application/x-www-form-urlencoded
or multipart/form-data
, depending on the form structure.
The ALTCHA payload will be embedded as the altcha
field (customizable via the name
attribute in the widget).
Use the value of the altcha
field as the payload
in the examples below. The payload is a Base64-JSON-encoded string.
Solution validation
Here is a pseudo-code example for validating a solution on the server:
Example
The official JS library works with Node.js, Bun and Deno.
For more examples and integrations, refer to the Community Integrations page.
Security recommendations
-
Replay attacks
To prevent the vulnerability of “replay attacks,” where a client resubmits the same solution multiple times, the server should implement measures that invalidate previously solved challenges.
The server should maintain a registry of solved challenges and reject any submissions that attempt to reuse a challenge that has already been successfully solved.
-
Challenge expiration
Limiting the validity period of challenges can bolster security measures, ensuring challenges cannot be exploited indefinitely. Implementing challenge expiration involves setting a time limit within which a challenge must be solved and submitted.
One effective method to achieve challenge expiration involves incorporating a server timestamp into the challenge’s
salt
during its generation.Starting from version 0.4 of the widget, you can utilize salt parameters and include the
?expires=<unix_ts>
parameter in the salt. The widget will automatically detect theexpires
parameter. Your server should then verify the expiration during the verification process.