Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Altcha Laravel Package

grantholle/laravel-altcha

Laravel ALTCHA offers a privacy-friendly, proof-of-work CAPTCHA alternative for Laravel apps. Add the Blade widget, verify submissions server-side, and configure challenges without third-party tracking or frustrating image puzzles.

View on GitHub
Deep Wiki
Context7

Getting Started

grantholle/laravel-altcha wraps the altcha-org/altcha PHP library so you can plug a privacy-friendly, proof-of-work CAPTCHA into a Laravel app in a couple of lines. The flow is: the browser solves a challenge (via the <altcha-widget> web component), submits a base64 payload back to your server, and Laravel verifies it against a signed HMAC.

Minimal setup:

  1. composer require grantholle/laravel-altcha

  2. Publish the config: php artisan vendor:publish --tag=altcha-config

  3. Generate an HMAC secret and put it in .env:

    ALTCHA_HMAC_KEY=base64:some-long-random-string
    
  4. Add the widget to your form (Blade shown, same idea in Livewire/Inertia):

    <script src="https://cdn.jsdelivr.net/npm/altcha/dist/altcha.min.js" type="module" defer></script>
    <altcha-widget challengeurl="{{ route('altcha.challenge') }}"></altcha-widget>
    
  5. Validate on the server:

    use Grantholle\LaravelAltcha\Rules\Altcha;
    
    $request->validate([
        'altcha' => ['required', new Altcha()],
    ]);
    

The first place to look is config/altcha.php — it controls the HMAC key, algorithm, cost (work factor), expiry window, and (as of 2.3.0) the new single-use toggle. Then skim src/Rules/Altcha.php — it's tiny and tells you exactly what the rule asserts.

The simplest first use case is protecting a public form (contact, registration, password reset) where you want bot friction without a third-party service or cookies.

Implementation Patterns

FormRequest-based validation. Wrap the rule in a FormRequest so it's testable and consistent:

class ContactRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'email' => ['required', 'email'],
            'message' => ['required', 'string', 'max:5000'],
            'altcha' => ['required', new Altcha()],
        ];
    }
}

Route registration. The package registers a challenge route (typically GET /altcha/challenge) out of the box. If you need to customize path, middleware, rate limiting, or throttling, publish/override the config and re-register the route yourself with Route::get(...) pointing at the package controller.

API/SPA flows. For JSON APIs, include the altcha payload in the request body and return a structured 422 with errors.altcha — the rule plays nicely with Laravel's validation response since it's a standard rule.

Single-use solutions (new in 2.3.0). The release adds opt-in single-use solutions on top of altcha-org/altcha v2. Enable it when replay of a solved challenge is a real risk (login, password reset, payment initiation). The pattern is:

  • Turn on the single-use flag in config/altcha.php.
  • Ensure your cache/database store is available and shared across web workers — the consumed solution must be recorded somewhere all request workers can see.
  • Expect a small failure rate for legitimate users who double-submit or hit a back-button/refresh — this is the point of the feature, so surface a clear "please solve the challenge again" error.

Rate limiting the challenge endpoint. The challenge endpoint is cheap to serve but should still be throttled (throttle:60,1) — otherwise bots can farm challenges to burn CPU elsewhere. Do this via route middleware or a wrapper route.

Testing. In feature tests, the easiest path is binding a fake rule that always passes, or generating a valid solution in-test against the configured HMAC key. Do not disable the rule globally — assert that the rule fails for missing/tampered payloads in at least one test.

Inertia/Inertia + Vue/React. Mount the <altcha-widget> the same way; the payload comes back as a hidden input named altcha and flows through your useForm submission as-is.

Gotchas and Tips

  • HMAC key rotation invalidates in-flight challenges. If you rotate ALTCHA_HMAC_KEY while a form is open, that user's solve is rejected. Either rotate in quiet periods or support two keys during a transition window (you'll need to hook into the rule).
  • The 2.3.0 upgrade to altcha-org/altcha v2 is the load-bearing change. If you've pinned the underlying library independently, or written code against its internals, review the upstream changelog — a major bump can change constructor signatures, algorithm names, or the encoded payload format. Verify your stored challenge payload shape in tests, not just the happy path.
  • Single-use is opt-in and stateful. Enabling it makes verification depend on a shared store (cache, Redis, DB). If you use the array cache driver in tests or a per-process driver in production (e.g. file on a multi-worker fleet), single-use silently doesn't protect you. Use Redis or the database.
  • Expiry is real. Challenges are time-bounded (expires). Very slow forms, or users who open a tab and come back the next day, will submit a stale solution. Keep the window generous (a few minutes) unless the form is a login.
  • cost is a UX/security dial, not a firewall. Higher cost slows every legit user. Tune against real low-end mobile hardware, not your dev laptop.
  • CDN + CSP. The widget is loaded from jsdelivr; if you have a strict Content-Security-Policy you must allow cdn.jsdelivr.net for script-src and connect-src (it fetches the challenge endpoint). Self-host the widget bundle if CDN isn't acceptable.
  • Don't trust the widget alone. The rule must be server-side on every endpoint that matters. Hiding a submit button client-side is not validation.
  • Debugging failures. Distinguish "challenge invalid/expired" from "solution tampered" from "already used" (2.3.0). The rule's failure message tells you which. Log the failure reason — it makes diagnosing real user complaints far faster, and a wave of "already used" errors usually means a double-submit bug in your frontend, not an attack.
  • Extension points. The rule class is small and easy to subclass if you need custom messaging, an extra check (e.g. blocklist of solver fingerprints), or a two-key rotation window. The config file is the primary knobs surface — avoid patching vendor files; wrap instead.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo