Add Google reCAPTCHA v2 to form in CodeIgniter 4

Google reCaptcha helps to protect the website against spam and bot submissions. It is mainly applied to login, registration, contact us, and add comment forms.

There are 2 versions of Google reCaptcha –

  1. v2 – User needs to select images based on the question.
  2. v3 – This is an invisible type of captcha.

In this tutorial, I show how you can add google recpatcha v2 to your form with validation in the CodeIgniter 4 project.

Add Google reCAPTCHA v2 to form in CodeIgniter 4


Contents

  1. Get Google reCaptcha keys
  2. Create variables in .env
  3. Enable CSRF
  4. Create custom validation for reCaptcha
  5. Create Controller
  6. Routes
  7. Create View
  8. Output
  9. Conclusion

1. Get Google reCaptcha keys

You can skip this step if you already registered for Google reCAPTCHA v2 and have site and secret keys.

  • Navigate to the following link for registering the website for reCaptcha.
  • Following page will display. Here, enter a label, select reCAPTCHA v2 from the reCAPTCHA type, and then “I’m not a robot” Checkbox if not selected. Specify domain names where you want to use and you can also specify localhost if you want to test it on your system.
  • Click the Submit button.

Google reCAPTCHA v2 creation

  • After submitting a new page display that has a site and secret keys.

Google recaptcha v2 site and secret keys

  • Copy the keys.

2. Create variables in .env

  • Open .env file which is available at the project root.

NOTE – If dot (.) not added at the start then rename the file to .env.

  • Here, define 2 variables for storing the captcha site and secret keys –
GOOGLE_RECAPTCHA_SITEKEY = 6LfGNWsjAAAAAL8pSk9JRfoe4StH6GJxAm9qc38g
GOOGLE_RECAPTCHA_SECRETKEY = 6LfGNWsjAAAAAGOVwDKbCLNm_c9NS49GNOsO1Ol-

3. Enable CSRF

  • Again open .env file.
  • Remove # from the start of the security.tokenName,security.headerName, security.cookieName, security.expires,and security.regenerate.
  • I update the security.tokenName value with 'csrf_hash_name'. With this name read CSRF hash. You can update it with any other value.
  • If you don’t want to regenerate CSRF hash after each request then set security.regenerate = false.
security.tokenName = 'csrf_hash_name' 
security.headerName = 'X-CSRF-TOKEN' 
security.cookieName = 'csrf_cookie_name' 
security.expires = 7200 
security.regenerate = true
  • Open app/Config/Filters.php file.
  • Uncomment 'csrf' in 'before' if commented.
// Always applied before every request
public $globals = [
    'before' => [
         // 'honeypot',
         'csrf',
         // 'invalidchars',
    ],
    'after' => [
        'toolbar',
        // 'honeypot',
        // 'secureheaders',
    ],
];

4. Create custom validation for reCaptcha

  • Create a new CaptchaValidation.php file in app/Config/ folder.
  • Create CaptchaValidation class and a verifyrecaptcha() method.
  • This method name – verifyrecaptcha use for calling while defining validation in the controller.
  • Read secret key from .env and assign to $secretkey. Here, $str has recaptcha response.
  • If $str is not empty then send the request to –
"https://www.google.com/recaptcha/api/siteverify?secret=".$secretkey."&response=".$str."&remoteip=".$_SERVER['REMOTE_ADDR']

for verification. Here, pass $secreteky,$str, and $_SERVER['REMOTE_ADDR'].

  • If response is successfully returned then return true otherwise, return false and assign error message to $error variable.

Completed Code

<?php 
namespace Config;

class CaptchaValidation{

    public function verifyrecaptcha(string $str, ?string &$error = null): bool
    {
          $secretkey = getenv('GOOGLE_RECAPTCHA_SECRETKEY');

          if(($str) && !empty($str)) {

                $response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secretkey."&response=".$str."&remoteip=".$_SERVER['REMOTE_ADDR']);

                $responseData = json_decode($response);
                if($responseData->success) { // Verified
                      return true;
                }
          }

          $error = "Invalid captacha";

          return false;
    }

}

Update Validation.php

For using the above-created Validation need to update the Validation.php file.

  • Open app/Config/Validation.php file.
  • Include Config\CaptchaValidation class.
  • Specify CaptchaValidation::class in $ruleSets Array.

Completed Code

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Validation\CreditCardRules;
use CodeIgniter\Validation\FileRules;
use CodeIgniter\Validation\FormatRules;
use CodeIgniter\Validation\Rules;
use Config\CaptchaValidation; // Custom reCAPTCHA validation

class Validation extends BaseConfig
{
      // --------------------------------------------------------------------
      // Setup
      // --------------------------------------------------------------------

      /**
      * Stores the classes that contain the
      * rules that are available.
      *
      * @var string[]
      */
      public $ruleSets = [
           Rules::class,
           FormatRules::class,
           FileRules::class,
           CreditCardRules::class,
           CaptchaValidation::class, // Custom reCAPTCHA validation
      ];

      /**
      * Specifies the views that are used to display the
      * errors.
      *
      * @var array<string, string>
      */
      public $templates = [
           'list' => 'CodeIgniter\Validation\Views\list',
           'single' => 'CodeIgniter\Validation\Views\single',
      ];

      // --------------------------------------------------------------------
      // Rules
      // --------------------------------------------------------------------
}

5. Create Controller

  • Create PagesController Controller.
php spark make:controller PagesController
  • Create 2 methods –
    • index() – Load index view.
    • submitcontactus() – This method calls on form submit.

Define validation. Here, for g-recaptcha-response specify verifyrecaptcha with required.

If validation is failed then return to the page with the validation response otherwise set SESSION flash message and redirect to route('/').

Completed Code

<?php

namespace App\Controllers;

use App\Controllers\BaseController;

class PagesController extends BaseController{

     public function index(){
          return view('index'); 
     }

     public function submitcontactus(){

          // Validation
          $input = $this->validate([
               'name' => 'required',
               'email' => 'required',
               'subject' => 'required',
               'message' => 'required',
               'g-recaptcha-response' => 'required|verifyrecaptcha',
            ],[
               'g-recaptcha-response' => [
               'required' => 'Please verify captcha',
            ],
          ]);

          if (!$input) { // Not valid

               $data['validation'] = $this->validator;

               return redirect()->back()->withInput()->with('validation', $this->validator);

          }else{ 
               // Set Session
               session()->setFlashdata('message', 'Submitted Successfully!');
               session()->setFlashdata('alert-class', 'alert-success');

          }
          return redirect()->route('/');

     }
}

6. Routes

  • Open app/Config/Routes.php file.
  • Here, create 2 routes –
    • page/submitcontactus – Handle form submit.
$routes->get('/', 'PagesController::index');
$routes->post('page/submitcontactus', 'PagesController::submitcontactus');

7. Create View

  • Create index.php file in app/Views/ folder.
  • Include recaptcha js in <head > section –
<script src='https://www.google.com/recaptcha/api.js'></script>
  • Create a simple contact <form >. Set action url to <?=site_url('page/submitcontactus')?>.
  • Add Google reCaptcha container. Here, <div > has class="g-recaptcha" and data-sitekey="<?= getenv('GOOGLE_RECAPTCHA_SITEKEY') ?>".
<div class="g-recaptcha" data-sitekey="<?= getenv('GOOGLE_RECAPTCHA_SITEKEY') ?>"></div>

Completed Code

<!DOCTYPE html>
<html>
<head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Add Google reCAPTCHA v2 to form in CodeIgniter 4</title>

     <!-- Bootstrap CSS -->
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" >

     <!-- reCAPTCHA JS-->
     <script src='https://www.google.com/recaptcha/api.js'></script>

</head>
<body>

     <div class="container">

         <div class="row">
               <div class="col-md-6 mt-5" style="margin: 0 auto;">

                    <?php 
                    // Display Response
                    if(session()->has('message')){
                    ?>
                          <div class="alert <?= session()->getFlashdata('alert-class') ?>">
                                <?= session()->getFlashdata('message') ?>
                          </div>
                    <?php
                    }
                    ?>

                    <h2 class="mb-4">Contact US</h2>

                    <?php $validation = \Config\Services::validation(); ?>

                    <form method="post" action="<?=site_url('page/submitcontactus')?>">

                         <?= csrf_field(); ?> 
                         <div class="form-group mb-4">
                               <label class="control-label col-sm-2" for="name">Name:</label>
                               <div class="col-sm-10">
                                     <input type="text" class="form-control" id="name" placeholder="Enter Name" name="name" value="<?= old('name') ?>">
                               </div>

                               <!-- Error -->
                               <?php if( $validation->getError('name') ) {?>
                                      <div class='text-danger mt-2'>
                                           * <?= $validation->getError('name'); ?>
                                      </div>
                               <?php }?>
                         </div>
                         <div class="form-group mb-4">
                               <label class="control-label col-sm-2" for="email">Email:</label>
                               <div class="col-sm-10">
                                      <input type="email" class="form-control" id="email" placeholder="Enter Email" name="email" value="<?= old('email') ?>">
                               </div>

                               <!-- Error -->
                               <?php if( $validation->getError('email') ) {?>
                                      <div class='text-danger mt-2'>
                                            * <?= $validation->getError('email'); ?>
                                      </div>
                               <?php }?>
                         </div>
                         <div class="form-group mb-4">
                               <label class="control-label col-sm-2" for="subject">Subject:</label>
                               <div class="col-sm-10">
                                     <input type="text" class="form-control" id="subject" placeholder="Enter Subject" name="subject" value="<?= old('subject') ?>" >
                               </div>

                               <!-- Error -->
                               <?php if( $validation->getError('subject') ) {?>
                                     <div class='text-danger mt-2'>
                                            * <?= $validation->getError('subject'); ?>
                                     </div>
                               <?php }?>
                         </div>
                         <div class="form-group mb-4">
                               <label class="control-label col-sm-2" for="message">Message:</label>
                               <div class="col-sm-10">
                                     <textarea class="form-control" id="message" name="message"><?= old('message') ?></textarea>
                               </div>

                               <!-- Error -->
                               <?php if( $validation->getError('message') ) {?>
                                     <div class='text-danger mt-2'>
                                           * <?= $validation->getError('message'); ?>
                                     </div>
                               <?php }?>
                         </div>
                         <div class="form-group mb-4">
                               <!-- reCAPTCHA -->
                               <div class="g-recaptcha" 
                                    data-sitekey="<?= getenv('GOOGLE_RECAPTCHA_SITEKEY') ?>"
                               ></div>

                               <!-- Error -->
                               <?php if( $validation->getError('g-recaptcha-response') ) {?>
                                     <div class='text-danger mt-2'>
                                            * <?= $validation->getError('g-recaptcha-response'); ?>
                                     </div>
                               <?php }?>

                         </div>
                         <div class="form-group "> 
                               <div class="col-sm-offset-2 col-sm-10">
                                     <button type="submit" class="btn btn-info">Submit</button>
                               </div>
                         </div>
                    </form>
               </div>
         </div>

     </div>

</body>
</html>

8. Output

View Output


9. Conclusion

I hope this tutorial helps you to successfully add Google reCaptcha v2 to your page.

You can also this tutorial if you want to know Google reCAPTCHA v3 implementation in CodeIgniter 4.

If you found this tutorial helpful then don't forget to share.

Leave a Comment