laravel-rebel-bot-protection
GitHub repository · Composer: padosoft/laravel-rebel-bot-protection · MIT
Stop the bots before they cost you an SMS. A single, swappable CAPTCHA gate that verifies
Cloudflare Turnstile, Google reCAPTCHA v3 and hCaptcha tokens server-side, fails closed by
default, and writes every decision to the Rebel audit trail.
What it is
A focused implementation of the core BotProtection contract. It takes the CAPTCHA token your
front-end already collected, verifies it against the provider’s API from the server, and returns a
clean pass/fail verdict the rest of the suite can act on. Three providers ship out of the box —
Turnstile, reCAPTCHA v3 and hCaptcha — behind one common interface, so switching vendors
is a config change, not a rewrite.
The problem it solves
Bots don’t just spam forms — on an auth flow they trigger real OTP sends, and every fake SMS is
money out the door plus noise in your security metrics. Client-side CAPTCHA widgets alone prove
nothing: the token has to be verified on the server, and the gate has to fail closed so a provider
outage can’t silently wave attackers through. This package puts that verification in one auditable
place, in front of the flows that cost you money.
What you get
- Three providers, one contract —
TurnstileBotProtection,RecaptchaBotProtection,
HcaptchaBotProtection, all behind the coreBotProtectioninterface. - Fail-closed by default — an unverifiable token is a denied request, not an open door.
- Server-side verification —
HttpCaptchaVerifiertalks to the provider;VerificationResult
carries the structured outcome. - Fully audited — every verdict flows through the core audit vocabulary, so the admin panel and
AI guard can see bot pressure across the whole suite. - Testable end-to-end —
FakeCaptchaVerifierandAlwaysPassBotProtectionlet you exercise the
gate without hitting a real provider.
When to use it
- You send OTPs / 2FA codes and want a gate before the SMS or email goes out.
- You need server-side CAPTCHA verification, not just a front-end widget.
- You want to switch between Turnstile, reCAPTCHA v3 and hCaptcha without touching call sites.
- You need bot decisions to land in the same audit trail as the rest of your auth events.
Worked example
composer require padosoft/laravel-rebel-bot-protection
php artisan vendor:publish
Configure your provider and keys in config/rebel-bot-protection.php, then let the suite resolve the
core BotProtection contract — the selected driver verifies tokens server-side and fails closed when
verification can’t complete.
How it fits
Bot protection sits at the front edge of an auth flow. It binds the core BotProtection contract,
so step-up, OTP and login flows gate on it without knowing which provider is configured. Because every
verdict is audited through laravel-rebel-core, bot pressure shows up in the admin API and the AI
guard alongside every other signal.
A pluggable, fail-closed, fully-audited CAPTCHA gate is rarer than it sounds — see the breakdown in
Why Rebel.
Reference
Runtime files
src\Contracts\CaptchaVerifier.phpsrc\Gateway\HttpCaptchaVerifier.phpsrc\Providers\AbstractCaptchaBotProtection.phpsrc\Providers\AlwaysPassBotProtection.phpsrc\Providers\HcaptchaBotProtection.phpsrc\Providers\RecaptchaBotProtection.phpsrc\Providers\TurnstileBotProtection.phpsrc\Testing\FakeCaptchaVerifier.phpsrc\Verification\VerificationResult.phpsrc\RebelBotProtectionServiceProvider.php
Service providers
src\Providers\AbstractCaptchaBotProtection.phpsrc\Providers\AlwaysPassBotProtection.phpsrc\Providers\HcaptchaBotProtection.phpsrc\Providers\RecaptchaBotProtection.phpsrc\Providers\TurnstileBotProtection.phpsrc\RebelBotProtectionServiceProvider.php
Services and managers
src\Contracts\CaptchaVerifier.phpsrc\Gateway\HttpCaptchaVerifier.phpsrc\Testing\FakeCaptchaVerifier.phpsrc\RebelBotProtectionServiceProvider.php
Contracts
src\Contracts\CaptchaVerifier.php
Controllers
None detected in the package tree.
Middleware
None detected in the package tree.
Models
None detected in the package tree.
Config
config\rebel-bot-protection.php
Migrations
None detected in the package tree.
Routes
None detected in the package tree.
Commands
None detected in the package tree.
Composer requirements
| Dependency | Constraint |
|---|---|
illuminate/contracts |
`^12.0 |
illuminate/support |
`^12.0 |
padosoft/laravel-rebel-core |
^0.1 |
php |
^8.3 |
spatie/laravel-package-tools |
^1.92 |
Development requirements
| Dependency | Constraint |
|---|---|
larastan/larastan |
^3.0 |
laravel/pint |
^1.18 |
orchestra/testbench |
`^10.0 |
pestphp/pest |
^4.0 |
pestphp/pest-plugin-laravel |
^4.0 |
Architecture decisions
Problem: keep laravel-rebel-bot-protection replaceable
Decision: document its public responsibility and use Rebel core contracts at integration boundaries.
Consequences: applications can adopt the package without coupling every other Rebel module to its internals.
Problem: package-specific behavior must remain auditable
Decision: all security-significant outcomes should emit or feed audit events through the core vocabulary.
Consequences: admin API, admin UI and AI guard can reason across packages without bespoke parsers for every provider.
Test & verification surface
tests\Feature\AlwaysPassBotProtectionTest.phptests\Feature\CaptchaProviderTest.phptests\Feature\DriverSelectionTest.phptests\Feature\HttpCaptchaVerifierTest.phptests\Live\CaptchaLiveTest.phptests\Support\SpyAuditLogger.phptests\Pest.phptests\TestCase.php
Do not copy internal test-only classes into an application. Treat file lists as a source map for maintainers and auditors, not as an installation recipe by themselves.