PHPackages                             climactic/laravel-altcha - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. climactic/laravel-altcha

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

climactic/laravel-altcha
========================

ALTCHA proof-of-work spam protection for Laravel — drop-in middleware, validation rule, and challenge endpoint.

0.1.1(3mo ago)218MITPHPPHP ^8.4CI passing

Since Apr 17Pushed 3mo agoCompare

[ Source](https://github.com/Climactic/laravel-altcha)[ Packagist](https://packagist.org/packages/climactic/laravel-altcha)[ Docs](https://github.com/climactic/laravel-altcha)[ GitHub Sponsors](https://github.com/climactic)[ RSS](/packages/climactic-laravel-altcha/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (13)Versions (3)Used By (0)

[![Laravel Altcha](.github/assets/banner.png)](.github/assets/banner.png)Laravel Altcha
==============

[](#laravel-altcha)

Drop-in [ALTCHA](https://altcha.org) proof-of-work spam protection for Laravel. Privacy-first, self-hosted, no third-party services, no tracking — just a middleware, a validation rule, and a challenge endpoint.

[![Discord](https://camo.githubusercontent.com/a2d0c0993adc0d0f466338c3991d1d318ab74795b52e1d5e4a2e41efc27acfb1/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f3330333139353332323531343031343231303f7374796c653d666f722d7468652d6261646765)](https://discord.gg/kedWdzwwR5)[![Latest Version on Packagist](https://camo.githubusercontent.com/c161651232dc91c41fd715fca6818be6fc2319d3b701a77b08e415f097f57e9b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f636c696d61637469632f6c61726176656c2d616c746368612e7376673f7374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/climactic/laravel-altcha)[![GitHub Tests Action Status](https://camo.githubusercontent.com/0a9b50129be6a3edee9119dc7a6798e201390f88aee64fa7c801488d7afcd028/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f636c696d61637469632f6c61726176656c2d616c746368612f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666f722d7468652d6261646765)](https://github.com/climactic/laravel-altcha/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/cad545372c8643c17a9f13412a54ca23187b09c97f581ad7ccc9a64f0825ad97/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f636c696d61637469632f6c61726176656c2d616c746368612f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666f722d7468652d6261646765)](https://github.com/climactic/laravel-altcha/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/be5e0adf6e2546f1a74b1d7738f08cf5bce56702daf3955b87dc4191202a4c14/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f636c696d61637469632f6c61726176656c2d616c746368612e7376673f7374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/climactic/laravel-altcha)[![Sponsor on GitHub](https://camo.githubusercontent.com/b3163f75bf5ed93d5cdab93ef38cdf453559a26611bab9abe917d7dee974979a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53706f6e736f722d4769744875622d6561346161613f7374796c653d666f722d7468652d6261646765266c6f676f3d676974687562)](https://github.com/sponsors/climactic)[![Support on Ko-fi](https://camo.githubusercontent.com/b5dfdef80a44c8875071357e6b7e2ef1f3c595e89a0b947682d5b12a58722d9e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f537570706f72742d4b6f2d2d66692d4646354535423f7374796c653d666f722d7468652d6261646765266c6f676f3d6b6f2d6669266c6f676f436f6c6f723d7768697465)](https://ko-fi.com/ClimacticCo)

📖 Table of Contents
-------------------

[](#-table-of-contents)

- [Laravel Altcha](#laravel-altcha)
    - [📖 Table of Contents](#-table-of-contents)
    - [Features](#features)
    - [🌟 Sponsors](#-sponsors)
    - [📦 Installation](#-installation)
    - [⚙️ Configuration](#%EF%B8%8F-configuration)
        - [Environment Variables](#environment-variables)
        - [Algorithms](#algorithms)
    - [🚀 Usage](#-usage)
        - [🛡️ Middleware](#%EF%B8%8F-middleware)
        - [✅ Validation Rule](#-validation-rule)
        - [🎯 Challenge Endpoint](#-challenge-endpoint)
        - [🧩 Frontend Integration](#-frontend-integration)
            - [React (Inertia) stubs](#react-inertia-stubs)
            - [Other frameworks](#other-frameworks)
        - [🔁 Replay Prevention](#-replay-prevention)
        - [🧮 Custom Verification](#-custom-verification)
    - [📚 API Reference](#-api-reference)
        - [🔧 Classes](#-classes)
        - [🧠 Middleware Behavior](#-middleware-behavior)
        - [🧾 Verifier Reasons](#-verifier-reasons)
    - [🧪 Testing](#-testing)
    - [📋 Changelog](#-changelog)
    - [🤝 Contributing](#-contributing)
    - [🔒 Security Vulnerabilities](#-security-vulnerabilities)
    - [💖 Support This Project](#-support-this-project)
    - [⭐ Star History](#-star-history)
    - [📦 Other Packages](#-other-packages)
    - [📄 License](#-license)
    - [⚖️ Disclaimer](#%EF%B8%8F-disclaimer)

Features
--------

[](#features)

- 🛡️ **Drop-in middleware** — protect any POST route with a single `altcha` alias
- ✅ **Validation rule** — use `new Altcha()` in FormRequests and inline validators
- 🎯 **Auto-registered challenge endpoint** — `GET /altcha` works out of the box, fully customizable
- 🔁 **Replay prevention** — challenges are single-use, cached by signature
- 🔀 **Pluggable algorithms** — PBKDF2, Argon2id, or Scrypt
- ⚡ **Optional fast verification** — skip re-derivation with a secondary HMAC key
- 🧩 **Framework-agnostic frontend** — React/TypeScript stubs shipped; any framework supported via the `altcha` web component
- 🌐 **i18n-friendly** — all user-facing messages routed through `__()`
- 🧪 **Tested** — 14 feature tests across middleware, rule, and endpoint
- 🔒 **Privacy-first** — no cookies, no fingerprinting, no third-party calls, GDPR/HIPAA/CCPA compliant

Built on [`altcha-org/altcha`](https://github.com/altcha-org/altcha-lib-php) v2 (PoW v2).

🌟 Sponsors
----------

[](#-sponsors)

*Your logo here* — Become a sponsor and get your logo featured in this README and on our website.

**Interested in title sponsorship?** Contact us at  for premium placement and recognition.

📦 Installation
--------------

[](#-installation)

Install the package via Composer:

```
composer require climactic/laravel-altcha
```

Publish the config:

```
php artisan vendor:publish --tag="laravel-altcha-config"
```

Add the required env vars:

```
ALTCHA_ENABLED=true
ALTCHA_HMAC_SECRET=
```

> 💡 Generate a strong secret with `php -r "echo bin2hex(random_bytes(32));"`.

⚙️ Configuration
----------------

[](#️-configuration)

The published `config/altcha.php` exposes everything you might want to tune:

```
return [
    'enabled' => (bool) env('ALTCHA_ENABLED', false),
    'hmac_secret' => env('ALTCHA_HMAC_SECRET'),
    'hmac_key_secret' => env('ALTCHA_HMAC_KEY_SECRET'),
    'algorithm' => env('ALTCHA_ALGORITHM', 'pbkdf2'),
    'cost' => (int) env('ALTCHA_COST', 10000),
    'expires' => (int) env('ALTCHA_EXPIRES', 300),
    'memory_cost' => ...,
    'parallelism' => ...,
    'cache_store' => env('ALTCHA_CACHE_STORE'),
    'field' => env('ALTCHA_FIELD', 'altcha'),
    'route' => [
        'enabled' => true,
        'path' => 'altcha',
        'name' => 'altcha.challenge',
        'prefix' => '',
        'domain' => null,
        'middleware' => ['web'],
    ],
];
```

### Environment Variables

[](#environment-variables)

KeyEnvDefaultNotes`enabled``ALTCHA_ENABLED``false`Master switch. When false, middleware and rule pass-through and the endpoint returns 404.`hmac_secret``ALTCHA_HMAC_SECRET`—**Required** when enabled. Used to sign challenges.`hmac_key_secret``ALTCHA_HMAC_KEY_SECRET``null`Optional. Enables the fast verification path (skips re-derivation).`algorithm``ALTCHA_ALGORITHM``pbkdf2``pbkdf2`, `argon2id`, or `scrypt`.`cost``ALTCHA_COST``10000`PoW iterations / time cost. Higher = harder for bots.`expires``ALTCHA_EXPIRES``300`Challenge lifetime in seconds. Also used as the replay cache TTL.`memory_cost``ALTCHA_MEMORY_COST``null`Argon2id / Scrypt only.`parallelism``ALTCHA_PARALLELISM``null`Scrypt only.`cache_store``ALTCHA_CACHE_STORE`defaultCache store used for replay prevention.`field``ALTCHA_FIELD``altcha`Request field name the middleware/rule read from.`route.enabled``ALTCHA_ROUTE_ENABLED``true`Disable to register the endpoint yourself.`route.path``ALTCHA_ROUTE_PATH``altcha`Challenge endpoint path.`route.name``ALTCHA_ROUTE_NAME``altcha.challenge`Route name for `route()` helpers.`route.prefix``ALTCHA_ROUTE_PREFIX``''`Route group prefix.`route.domain``ALTCHA_ROUTE_DOMAIN``null`Route group domain.### Algorithms

[](#algorithms)

AlgorithmExtensionWhen to use`pbkdf2`built-inDefault. Works everywhere. Good baseline.`argon2id``ext-sodium`Strongest. Memory-hard — resistant to ASIC/GPU acceleration.`scrypt`[`php-scrypt`](https://github.com/DomBlack/php-scrypt)Memory-hard alternative.🚀 Usage
-------

[](#-usage)

### 🛡️ Middleware

[](#️-middleware)

Protect any POST route with the `altcha` middleware alias:

```
use Illuminate\Support\Facades\Route;

Route::post('/contact', ContactController::class)->middleware('altcha');
Route::post('/register', RegisterController::class)->middleware('altcha');
```

Works inside a middleware group too:

```
Route::middleware(['web', 'altcha'])->group(function () {
    Route::post('/enterprise', EnterpriseController::class);
    Route::post('/waitlist', WaitlistController::class);
});
```

Failed verifications throw a `ValidationException` with an error on the `altcha` field — so Inertia/Blade forms display the error like any other validation failure.

### ✅ Validation Rule

[](#-validation-rule)

For FormRequests and inline validators:

```
use Climactic\Altcha\Rules\Altcha;

public function rules(): array
{
    return [
        'email' => ['required', 'email'],
        'altcha' => [new Altcha()],
    ];
}
```

The rule is **implicit** — it runs even when the field is empty, so you don't need `required` unless you want its error message. When `altcha.enabled` is false, it passes silently.

### 🎯 Challenge Endpoint

[](#-challenge-endpoint)

`GET /altcha` is registered automatically and returns a signed challenge:

```
{
    "parameters": {
        "algorithm": "pbkdf2",
        "salt": "...",
        "cost": 10000
    },
    "signature": "..."
}
```

Customize via `config/altcha.php` — path, prefix, domain, and middleware group are all tunable. Set `route.enabled` to `false` and register the controller yourself if you need full control:

```
use Climactic\Altcha\Http\Controllers\AltchaChallengeController;

Route::get('/security/challenge', AltchaChallengeController::class)
    ->middleware(['web', 'throttle:60,1']);
```

### 🧩 Frontend Integration

[](#-frontend-integration)

Install the ALTCHA web component:

```
npm install altcha@^3
```

> ⚠️ Requires `altcha` npm v3 or higher. This package's backend emits the altcha v2 nested challenge payload (`{ parameters, signature }`), which only altcha JS v3+ can parse.

#### React (Inertia) stubs

[](#react-inertia-stubs)

Publish the TypeScript wrappers:

```
php artisan vendor:publish --tag="altcha-frontend"
```

This copies:

- `resources/js/components/altcha-widget.tsx` — React wrapper around the web component
- `resources/js/types/altcha.d.ts` — JSX types for ``

Then use it in any form:

```
import { AltchaWidget } from '@/components/altcha-widget';

export default function ContactForm() {
    return (

            Send

    );
}
```

The widget solves the challenge in a web worker and injects the solution into a hidden `altcha` input at submit time — totally invisible to your users.

#### Other frameworks

[](#other-frameworks)

Vue, Svelte, Solid, Lit, Alpine, and plain HTML work out of the box with the `altcha` npm package — no wrapper needed:

```

```

See the official [framework starters](https://github.com/altcha-org?q=altcha-starter) for idiomatic integrations.

### 🔁 Replay Prevention

[](#-replay-prevention)

Every valid solution is recorded in the cache using the challenge signature as the key. A second submission of the same payload fails with a replay error:

```
Security challenge has already been used. Please try again.

```

The record TTL equals `altcha.expires` (so entries self-expire when the challenge itself would have). Use the `cache_store` config to isolate this from your application's default cache.

### 🧮 Custom Verification

[](#-custom-verification)

Need to verify outside the middleware/rule (e.g. an API controller, a queued job)? Resolve the `Verifier`:

```
use Climactic\Altcha\Support\Verifier;

$result = app(Verifier::class)->verify($request->input('altcha'));

if (! $result->verified) {
    return response()->json([
        'error' => 'captcha',
        'reason' => $result->reason, // missing | malformed | invalid | expired | replay
    ], 422);
}
```

📚 API Reference
---------------

[](#-api-reference)

### 🔧 Classes

[](#-classes)

ClassPurpose`Climactic\Altcha\Http\Middleware\VerifyAltcha`Middleware registered under the `altcha` alias.`Climactic\Altcha\Http\Controllers\AltchaChallengeController`Invokable controller backing `GET /altcha`.`Climactic\Altcha\Rules\Altcha`Implicit `ValidationRule` implementation.`Climactic\Altcha\Support\Verifier`Core verification service. Resolvable from the container.`Climactic\Altcha\Support\VerificationResult`Immutable result value object (`verified`, `reason`, `replayKey`).`Climactic\Altcha\Support\AlgorithmFactory`Produces a `DeriveKeyInterface` for the configured algorithm.### 🧠 Middleware Behavior

[](#-middleware-behavior)

`VerifyAltcha` intentionally bypasses verification in a few cases so you can apply it broadly without extra logic:

ConditionOutcome`altcha.enabled` is `false`Pass-throughRequest method is not POSTPass-throughUser is authenticatedPass-throughMissing/invalid payload`ValidationException` on the `altcha` fieldValid payloadMarked used, request continues### 🧾 Verifier Reasons

[](#-verifier-reasons)

`VerificationResult::$reason` is one of:

ConstantStringMeaning`Verifier::REASON_MISSING``missing`No payload was submitted.`Verifier::REASON_MALFORMED``malformed`Payload wasn't valid base64 / JSON / shape.`Verifier::REASON_INVALID``invalid`Signature or derived key didn't match.`Verifier::REASON_EXPIRED``expired`Challenge passed `expiresAt`.`Verifier::REASON_REPLAY``replay`Payload was already accepted once.🧪 Testing
---------

[](#-testing)

```
composer test
```

Type check + lint:

```
composer analyse
composer format
```

📋 Changelog
-----------

[](#-changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

🤝 Contributing
--------------

[](#-contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details. You can also join our Discord server to discuss ideas and get help: [Discord Invite](https://discord.gg/kedWdzwwR5).

🔒 Security Vulnerabilities
--------------------------

[](#-security-vulnerabilities)

Please report security vulnerabilities to .

💖 Support This Project
----------------------

[](#-support-this-project)

Laravel Altcha is free and open source, built and maintained with care. If this package helps keep spam off your forms or saves you a Cloudflare Turnstile bill, please consider supporting its continued development.

[ ![Sponsor on GitHub](https://camo.githubusercontent.com/b54bfcc9644ed7bcc05286df7b65016fc35a3ef50ead57e5942733d1b7663048/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53706f6e736f722532306f6e2d4769744875622d6561346161613f7374796c653d666f722d7468652d6261646765266c6f676f3d676974687562)](https://github.com/sponsors/climactic) [ ![Support on Ko-fi](https://camo.githubusercontent.com/f29eb9e7ac04ba39e8f164bd49b7170f8d5263e726c135bfbebf865998f3b146/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f537570706f72742532306f6e2d4b6f2d2d66692d4646354535423f7374796c653d666f722d7468652d6261646765266c6f676f3d6b6f2d6669266c6f676f436f6c6f723d7768697465)](https://ko-fi.com/ClimacticCo)⭐ Star History
--------------

[](#-star-history)

[![Star History Chart](https://camo.githubusercontent.com/d6804ebc73e85a33158dfa1879d69bc086b593d0ba93af63ab08462ce2a0119c/68747470733a2f2f6170692e737461722d686973746f72792e636f6d2f7376673f7265706f733d636c696d61637469632f6c61726176656c2d616c7463686126747970653d64617465266c6567656e643d746f702d6c656674)](https://www.star-history.com/#climactic/laravel-altcha&type=date&legend=top-left)

📦 Other Packages
----------------

[](#-other-packages)

Check out our other Laravel packages:

PackageDescription🛡️ [laravel-spam](https://github.com/climactic/laravel-spam)Anti-spam toolkit: disposable-email and blocklist rules, StopForumSpam lookups, middleware, and a check API. Pairs naturally with Laravel Altcha.💳 [laravel-credits](https://github.com/climactic/laravel-credits)Ledger-based credit system for virtual currencies, reward points, and credit-based features, with transfers, metadata querying, and historical balances.🧾 [laravel-polar](https://github.com/climactic/laravel-polar)[Polar.sh](https://polar.sh) billing integration for Laravel — subscriptions, one-off purchases, webhooks, and license keys.📄 License
---------

[](#-license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

⚖️ Disclaimer
-------------

[](#️-disclaimer)

This package is not affiliated with Laravel or ALTCHA. It's for Laravel but is not by Laravel. Laravel is a trademark of Taylor Otwell. ALTCHA is a trademark of [Daniel Regeci / ALTCHA](https://altcha.org).

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance82

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

2

Last Release

95d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/04e8fd6548e1113d35fb74e60ba71ce472fcf61503f8bd0c5b2f0928910860d4?d=identicon)[climactic](/maintainers/climactic)

---

Top Contributors

[![adiologydev](https://avatars.githubusercontent.com/u/9266227?v=4)](https://github.com/adiologydev "adiologydev (7 commits)")

---

Tags

laravelspamcaptchaproof-of-workALTCHAclimactic

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/climactic-laravel-altcha/health.svg)

```
[![Health](https://phpackages.com/badges/climactic-laravel-altcha/health.svg)](https://phpackages.com/packages/climactic-laravel-altcha)
```

###  Alternatives

[spatie/laravel-permission

Permission handling for Laravel 12 and up

12.9k102.4M1.5k](/packages/spatie-laravel-permission)[spatie/laravel-pdf

Create PDFs in Laravel apps

1.0k4.8M48](/packages/spatie-laravel-pdf)[spatie/laravel-passkeys

Use passkeys in your Laravel app

472890.7k40](/packages/spatie-laravel-passkeys)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3914.8k](/packages/rawilk-profile-filament-plugin)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

45955.7k](/packages/harris21-laravel-fuse)[vormkracht10/laravel-mails

Laravel Mails can collect everything you might want to track about the mails that has been sent by your Laravel app.

24957.5k](/packages/vormkracht10-laravel-mails)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
