Google reCAPTCHA Integration

Protect your application's sensitive forms (login, registration, password reset, etc.) from automated abuse. The Rhapsody framework provides a seamless integration with Google reCAPTCHA v2 (Checkbox) through a Twig view injector and a corresponding validation rule.

Prerequisite: You must have a valid Google reCAPTCHA API key pair. Register your site here. Choose "reCAPTCHA v2" and "I'm not a robot" Checkbox.

Step 1: Environment Variables

Store your site and secret keys inside the application's .env file. The framework reads these values via $_ENV.

RECAPTCHA_SITE_KEY="your_site_key_here"
RECAPTCHA_SECRET_KEY="your_secret_key_here"
Note: If either key is missing or empty, the widget will not render and the server‑side validation will automatically fail. This prevents insecure fallback behaviour.

Step 2: Frontend Rendering

The base controller (or a custom view composer) automatically binds the reCAPTCHA script and widget markup to the captcha_form variable. You only need to print this variable inside your Twig form.

Critical: Because the variable contains raw HTML, you must use the Twig |raw filter. Without it, the browser will display the markup as plain text and the widget will not work.
<form action="/register" method="POST">
<!-- CSRF Protection – always include for POST forms -->
{{ csrf_field() }}

    <label for="email">Email</label>
    <input type="email" name="email" id="email" required>

    <!-- The reCAPTCHA widget will be inserted here -->
    {{ captcha_form|raw }}

    <button type="submit">Register</button>
</form>

The rendered HTML includes:

  • The Google API script (https://www.google.com/recaptcha/api.js) loaded asynchronously.
  • A div with class g-recaptcha and your site key as a data-sitekey attribute.

You can customise the widget by passing additional attributes (e.g., data-theme, data-size) by extending the Recaptcha::render() method – see the source code in Rhapsody\Core\Helpers\Recaptcha.


Step 3: Backend Validation Rule

The framework's validator includes a built‑in recaptcha rule. When applied to the field named g-recaptcha-response, it verifies the token with Google's API using your secret key.

public function store(Request $request)
{
    $rules = [
        'name'                 => 'required|alpha_num|min:3',
        'email'                => 'required|email|unique:User',
        'password'             => 'required|min:8|confirmed',
        'g-recaptcha-response' => 'required|recaptcha'
    ];

    if (! $this->validator->validate($request->post(), $rules)) {
        // Redirect back with error messages (flashed to session)
        return $this->redirectBackWithErrors($this->validator->getErrors());
    }

    // Registration logic – only reached if reCAPTCHA is valid
    // ...
}
Success: The recaptcha rule automatically handles:
  • Empty or missing token → validation fails.
  • Invalid secret key or network errors → validation fails (logged as a warning).
  • Valid token → passes, and you can safely proceed.

Manual Verification (Optional)

If you need to verify the token outside the validator (e.g., in an AJAX endpoint), you can use the static Recaptcha::verify() helper directly:

use Rhapsody\Core\Helpers\Recaptcha;

$responseToken = $request->post('g-recaptcha-response');
$clientIp      = $request->getClientIp();

if (Recaptcha::verify($responseToken, $clientIp)) {
    // Token is valid
} else {
    // Handle failure
}

The verify() method performs a POST request to Google's siteverify API using PHP's stream context – no external HTTP client is required.


Troubleshooting

  • Widget does not appear: Check that RECAPTCHA_SITE_KEY is set in your .env and that the variable is printed with |raw.
  • Validation always fails: Ensure your secret key is correct and that the domain in your Google admin panel matches your application's domain (including subdomain and protocol).
  • “Invalid input secret” error: The secret key may be mis‑typed or you may be using a different environment key than expected.
  • Rate limiting or timeouts: Google’s API may occasionally be slow; the helper returns false on any network error. Consider logging these failures for monitoring.

Testing reCAPTCHA in Your Test Suite

During automated testing, you might want to bypass the reCAPTCHA check. The easiest way is to mock the validation rule or the Recaptcha helper. See the Testing Suite documentation for details on using mock() to simulate a successful verification.