A Plug that serves a freshly signed ALTCHA v2 proof-of-work challenge as JSON.
Mount it wherever you want the challenge endpoint to live and point the ALTCHA
widget's challenge attribute at the same path.
This plug only handles GET requests; any other method passes through
untouched, so it is safe to place in a shared pipeline.
Configuration
Options given where the plug is mounted take precedence over application config:
# config/runtime.exs
config :altcha, Altcha.Plug.Challenge,
hmac_signature_secret: System.fetch_env!("ALTCHA_HMAC_SECRET")Options
:hmac_signature_secret(required) - secret used to sign the challenge parameters. Accepts a string, a zero-arity function, or an{module, function, args}tuple. Functions and MFA tuples are resolved on every request, so reading the value from the environment is safe.:hmac_key_signature_secret- secret for signing the pre-computed derived key. Only meaningful together with:counter(deterministic mode). Same value shapes as:hmac_signature_secret.:algorithm- key derivation algorithm string, default"PBKDF2/SHA-256".:cost- proof-of-work cost, default10_000.:expires_in- challenge lifetime in seconds, default600.:counter- fixed counter for deterministic challenges (advanced). A zero-arity function may be given to randomise it per request.
Usage
In a Phoenix router:
scope "/altcha" do
forward "/challenge", Altcha.Plug.Challenge
endAs a plain Plug pipeline entry:
plug Altcha.Plug.Challenge, cost: 50_000Config read at init time
Plug.Builder initialises plugs at compile time by default, so a secret
coming from config/runtime.exs is not yet available when init/1 runs in a
pipeline. Pass it inline, build the pipeline with init_mode: :runtime, or set
the key in a compile-time config file to a function/MFA value, which is then
resolved on every request. A Phoenix router forward calls init/1 per
request, so runtime config works there as-is.
On the client:
<altcha-widget challenge="/altcha/challenge"></altcha-widget>See the Phoenix integration guide for the full picture.