Weave Code
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

No Captcha Laravel Package

anhskohbo/no-captcha

Laravel package to integrate Google reCAPTCHA “No CAPTCHA” into your app. Provides helpers to render the JS, display normal or invisible widgets, and validate responses. Supports Laravel auto-discovery, with simple .env configuration for site key and secret.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require anhskohbo/no-captcha
    

    For Laravel ≥5.5, skip manual setup (auto-discovery enabled). For older versions, add the service provider and facade alias to config/app.php and publish the config:

    php artisan vendor:publish --provider="Anhskohbo\NoCaptcha\NoCaptchaServiceProvider"
    
  2. Configure .env:

    NOCAPTCHA_SECRET=your_recaptcha_secret_key
    NOCAPTCHA_SITEKEY=your_recaptcha_site_key
    

    Obtain keys from Google reCAPTCHA Admin.

  3. First Use Case: Add reCAPTCHA to a form in a Blade template:

    <!-- Render JavaScript (required for reCAPTCHA) -->
    {!! NoCaptcha::renderJs() !!}
    
    <!-- Display reCAPTCHA widget -->
    {!! NoCaptcha::display() !!}
    
    <!-- Form with validation -->
    <form method="POST" action="/submit">
        @csrf
        <!-- Other form fields -->
        <button type="submit">Submit</button>
    </form>
    
  4. Validate in Controller:

    use Anhskohbo\NoCaptcha\Facades\NoCaptcha;
    use Illuminate\Support\Facades\Validator;
    
    public function store(Request $request) {
        $validator = Validator::make($request->all(), [
            'g-recaptcha-response' => 'required|captcha',
            // Other validation rules...
        ]);
    
        if ($validator->fails()) {
            return redirect()->back()->withErrors($validator);
        }
    
        // Process form...
    }
    

Implementation Patterns

Common Workflows

1. Standard Form Protection

  • Frontend: Render JS and widget in Blade:
    {!! NoCaptcha::renderJs('en', false, 'onloadCallback') !!}
    {!! NoCaptcha::display(['data-theme' => 'light']) !!}
    
  • Backend: Validate in controller or Form Request:
    public function rules() {
        return [
            'g-recaptcha-response' => 'required|captcha',
        ];
    }
    

2. Invisible reCAPTCHA (v3)

  • Use displaySubmit() for forms where UX should be seamless:
    {!! NoCaptcha::displaySubmit('contact-form', 'Send Message') !!}
    
  • Note: Requires form ID for auto-submission on success. Validate with:
    $response = NoCaptcha::verifyResponse($request->input('g-recaptcha-response'));
    if (!$response->success()) {
        // Handle failure
    }
    

3. API Endpoint Protection

  • Middleware: Create a middleware to validate reCAPTCHA for API routes:
    namespace App\Http\Middleware;
    use Anhskohbo\NoCaptcha\Facades\NoCaptcha;
    use Closure;
    
    class VerifyRecaptcha {
        public function handle($request, Closure $next) {
            if ($request->isMethod('post') && !$request->has('g-recaptcha-response')) {
                return response()->json(['error' => 'CAPTCHA required'], 403);
            }
            $response = NoCaptcha::verifyResponse($request->input('g-recaptcha-response'));
            if (!$response->success()) {
                return response()->json(['error' => 'Invalid CAPTCHA'], 403);
            }
            return $next($request);
        }
    }
    
  • Register in app/Http/Kernel.php:
    protected $routeMiddleware = [
        'recaptcha' => \App\Http\Middleware\VerifyRecaptcha::class,
    ];
    
  • Apply to routes:
    Route::post('/api/submit', [Controller::class, 'store'])->middleware('recaptcha');
    

4. Dynamic reCAPTCHA Enforcement

  • Enable/disable per form or route using config:
    NOCAPTCHA_ENABLED=true
    
  • Conditionally render in Blade:
    @if(config('nocaptcha.enabled'))
        {!! NoCaptcha::renderJs() !!}
        {!! NoCaptcha::display() !!}
    @endif
    

5. Testing

  • Unit Tests: Mock the facade for validation tests:
    NoCaptcha::shouldReceive('verifyResponse')
        ->once()
        ->andReturn(new \Anhskohbo\NoCaptcha\NoCaptchaResponse(true));
    
  • HTTP Tests: Include g-recaptcha-response in test requests:
    $response = $this->post('/submit', [
        'g-recaptcha-response' => 'test-response',
        'name' => 'John',
    ]);
    

Integration Tips

  • Laravel Livewire/Alpine.js: Render reCAPTCHA dynamically:
    <div x-data="{ showCaptcha: false }">
        <button @click="showCaptcha = true">Submit</button>
        @if($showCaptcha)
            {!! NoCaptcha::renderJs() !!}
            {!! NoCaptcha::display() !!}
        @endif
    </div>
    
  • Inertia.js: Pass reCAPTCHA token via props:
    public function submit(StoreRequest $request) {
        return Inertia::render('Form', [
            'captchaVerified' => NoCaptcha::verifyResponse($request->input('g-recaptcha-response')),
        ]);
    }
    
  • Queue Jobs: Validate reCAPTCHA asynchronously for performance:
    public function store(Request $request) {
        $response = NoCaptcha::verifyResponse($request->input('g-recaptcha-response'));
        if (!$response->success()) {
            return back()->withErrors(['captcha' => 'Invalid']);
        }
        // Dispatch job for further processing
    }
    

Gotchas and Tips

Pitfalls

  1. Missing JavaScript:

    • Issue: Forgetting to call NoCaptcha::renderJs() before NoCaptcha::display() causes the widget to fail silently.
    • Fix: Always render JS in the <head> or before the widget. For dynamic forms, ensure JS is loaded before the widget appears.
  2. Validation Timing:

    • Issue: Validating g-recaptcha-response before the widget loads (e.g., in AJAX calls) may return false negatives.
    • Fix: Ensure the reCAPTCHA script is loaded before submission. For AJAX, load JS dynamically:
      grecaptcha.ready(function() {
          // Submit form
      });
      
  3. Form ID Mismatch:

    • Issue: Using displaySubmit() without matching the form ID causes the auto-submit feature to fail.
    • Fix: Verify the form ID in displaySubmit() matches the actual form:
      {!! NoCaptcha::displaySubmit('contact-form-id', 'Submit') !!}
      
      <form id="contact-form-id" method="POST">
      
  4. Environment Variables:

    • Issue: Hardcoding secret keys in config files instead of .env.
    • Fix: Always use .env for NOCAPTCHA_SECRET and NOCAPTCHA_SITEKEY. Never commit .env to version control.
  5. Rate Limiting:

    • Issue: Exceeding Google’s free tier (1M requests/day) without monitoring.
    • Fix: Monitor usage via Google’s reCAPTCHA Admin. Implement caching for high-traffic forms:
      $response = cache()->remember("recaptcha_{$request->ip()}", now()->addMinutes(5), function () use ($request) {
          return NoCaptcha::verifyResponse($request->input('g-recaptcha-response'));
      });
      
  6. Testing Assumptions:

    • Issue: Assuming NoCaptcha::verifyResponse() returns true in tests without mocking.
    • Fix: Always mock the facade in tests:
      NoCaptcha::shouldReceive('verifyResponse')
          ->andReturn(new \Anhskohbo\NoCaptcha\NoCaptchaResponse(true));
      

Debugging

  1. Widget Not Rendering:

    • Check browser console for errors (e.g., grecaptcha undefined). Ensure NoCaptcha::renderJs() is called.
    • Verify NOCAPTCHA_SITEKEY is correct in .env.
  2. Validation Failing:

    • Log the response object:
      $response = NoCaptcha::verifyResponse($request->input('g-recaptcha-response'));
      \Log::debug('reCAPTCHA Response', ['success' => $response->success(), 'error-codes' => $response->errorCodes()]);
      
    • Common error codes:
      • missing-input-secret: Invalid NOCAPTCHA_SECRET.
      • `invalid
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope