Integrating a CAPTCHA with the WordPress Registration Form

    Collins Agbonghama
    Collins Agbonghama
    Share

    In previous tutorials, we took a deep dive into WordPress HTTP API, learned how to use the HTTP API in consuming APIs in plugins during the course of building a widget that displays WHOIS and social data of a domain and integrating a CAPTCHA with the WordPress login form.

    In this tutorial, we will code a plugin that will this time around, integrate CAPTCHA (Google’s reCAPTCHA) to the default WordPress registration form. Of course, the HTTP API will be used to communicate with reCAPTCHA endpoint to verify the answer supplied by a user to the CAPTCHA challenge.

    Below is a screenshot of the registration form protected by CAPTCHA to prevent spam registration.

    CAPTCHA with the WordPress Registration Form

    Why Include a CAPTCHA with the Registration Form?

    Due to the increasing popularity of WordPress, it has become an easy target for unscrupulous automated software. This software crawls the web in search of websites built with WordPress and starts registering hundreds and thousands of accounts every minute.

    In my early WordPress days, I can still remember waking up one morning with my mailbox filled with notifications for over fifty registered user accounts.

    One of the proven and trusted ways of reducing and perhaps eliminating spam completely is by implementing CAPTCHAs to web forms.

    A CAPTCHA is a program that protects websites against bots by generating and grading tests that humans can pass and that current software programs cannot.

    By integrating CAPTCHA to a WordPress registration form, spam registration will soon become a thing of the past.

    Plugin Development

    Before we begin coding the plugin, let’s head over to reCAPTCHA, register your domain name and grab your public and private API keys.

    First off, include the plugin header.

    <?php
    
    /*
    Plugin Name: reCAPTCHA in WP Registration Form
    Plugin URI: https://www.sitepoint.com
    Description: Add Google's reCAPTCHA to WordPress registration form
    Version: 1.0
    Author: Agbonghama Collins
    Author URI: http://w3guy.com
    License: GPL2
    */
    Create a PHP class with two properties that will store your reCAPTCHA’s private and public key.
    class Captcha_Registration_Form {
    
    	/** @type string private key|public key */
    	private $public_key, $private_key;

    The plugin constructor method will consist of two action hooks that will add the CAPTCHA challenge to the registration form and verify the CAPTCHA response.

    /** class constructor */
    	public function __construct() {
    		$this->public_key  = '6Le6d-USAAAAAFuYXiezgJh6rDaQFPKFEi84yfMc';
    		$this->private_key = '6Le6d-USAAAAAKvV-30YdZbdl4DVmg_geKyUxF6b';
    
    		// adds the captcha to the registration form
    		add_action( 'register_form', array( $this, 'captcha_display' ) );
    
    		// authenticate the captcha answer
    		add_action( 'registration_errors', array( $this, 'validate_captcha_field' ), 10, 3 );
    	}

    The captcha_display() method that will output the reCAPTCHA challenge is added to the WordPress registration form by the register_form action.

    The validate_captcha_field() method that will ensure: the CAPTCHA field isn’t left empty and also verify the answer supplied by the user; is added to the registration validation system by the registration_errors action.

    Below is the code for the captcha_display() and validate_captcha_field() method we talked about.

    /** Output the reCAPTCHA form field. */
    	public function captcha_display() {
    		?>
    		<script type="text/javascript"
    		        src="http://www.google.com/recaptcha/api/challenge?k=<?=$this->public_key;?>">
    		</script>
    		<noscript>
    			<iframe src="http://www.google.com/recaptcha/api/noscript?k=<?=$this->public_key;?>"
    			        height="300" width="300" frameborder="0"></iframe>
    			<br>
    			<textarea name="recaptcha_challenge_field" rows="3" cols="40">
    			</textarea>
    			<input type="hidden" name="recaptcha_response_field"
    			       value="manual_challenge">
    		</noscript>
    
    	<?php
    	}
    /**
    	 * Verify the captcha answer
    	 *
    	 * @param $user string login username
    	 * @param $password string login password
    	 *
    	 * @return WP_Error|WP_user
    	 */
    	public function validate_captcha_field($errors, $sanitized_user_login, $user_email) {
    
    		if ( ! isset( $_POST['recaptcha_response_field'] ) || empty( $_POST['recaptcha_response_field'] ) ) {
    			$errors->add( 'empty_captcha', '<strong>ERROR</strong>: CAPTCHA should not be empty');
    		}
    
    		if( $this->recaptcha_response() == 'false' ) {
    			$errors->add( 'invalid_captcha', '<strong>ERROR</strong>: CAPTCHA response was incorrect');
    		}
    
    		return $errors;
    	}

    Taking a closer look at the validate_captcha_field() specifically the second if conditional statement, a call is made to recaptcha_response() to check if the CAPTCHA answer is correct (false is returned if the CAPTCHA response is wrong).

    Let’s see the code and explanation of recaptcha_response().

    /**
    	 * Get the reCAPTCHA API response.
    	 *
    	 * @return string
    	 */
    	public function recaptcha_response() {
    
    		// reCAPTCHA challenge post data
    		$challenge = isset($_POST['recaptcha_challenge_field']) ? esc_attr($_POST['recaptcha_challenge_field']) : '';
    
    		// reCAPTCHA response post data
    		$response  = isset($_POST['recaptcha_response_field']) ? esc_attr($_POST['recaptcha_response_field']) : '';
    
    		$remote_ip = $_SERVER["REMOTE_ADDR"];
    
    		$post_body = array(
    			'privatekey' => $this->private_key,
    			'remoteip'   => $remote_ip,
    			'challenge'  => $challenge,
    			'response'   => $response
    		);
    
    		return $this->recaptcha_post_request( $post_body );
    
    	}

    Code explanation: To verify that the CAPTCHA answer supplied by the user is correct, a POST request is sent to the endpoint http://www.google.com/recaptcha/api/verify with the following parameters.

    • privatekey Your private key
    • remoteip The IP address of the user who solved the CAPTCHA.
    • challenge The value of recaptcha_challenge_field sent via the form.
    • response The value of recaptcha_response_field sent via the form.

    First, the challenge and response POST data sent by the form is captured and saved to $challenge and $response respectively.

    The IP address of the user is captured by $_SERVER["REMOTE_ADDR"] and saved to $remote_ip.

    To send a POST request with the HTTP API, the parameters or body must be in an array form as shown below:

    $post_body = array(
    			'privatekey' => $this->private_key,
    			'remoteip'   => $remote_ip,
    			'challenge'  => $challenge,
    			'response'   => $response
    		);

    The POST parameters are passed as an argument to the recaptcha_post_request() which then sends the request along with the parameters to https://www.google.com/recaptcha/api/verify and return the API response.

    recaptcha_post_request() returns true if the CAPTCHA answer is correct and false otherwise.

    Below is the code for recaptcha_post_request()

    /**
    	 * Send HTTP POST request and return the response.
    	 *
    	 * @param $post_body array HTTP POST body
    	 *
    	 * @return bool
    	 */
    	public function recaptcha_post_request( $post_body ) {
    
    		$args = array( 'body' => $post_body );
    
    		// make a POST request to the Google reCaptcha Server
    		$request = wp_remote_post( 'https://www.google.com/recaptcha/api/verify', $args );
    
    		// get the request response body
    		$response_body = wp_remote_retrieve_body( $request );
    
    		/**
    		 * explode the response body and use the request_status
    		 * @see https://developers.google.com/recaptcha/docs/verify
    		 */
    		$answers = explode( "\n", $response_body );
    
    		$request_status = trim( $answers[0] );
    
    		return $request_status;
    	}

    Code explanation: An array $args with the POST body $post_body saved to the key body is created.

    The wp_remote_post sends the POST request with the response saved to $request.

    The response body is retrieved by the wp_remote_retrieve_body and saved to $response_body.

    If the CAPTCHA test was passed, the reCAPTCHA API returns:

    true
    success

    Otherwise the following error is returned

    false
    incorrect-captcha-sol

    To get the recaptcha_post_request method to return a Boolean value i.e. true on success and false on failure; the response $response_body is exploded and the array data with index 0 trimmed to remove any redundant white space from the beginning and end of the string.

    Finally, we close the plugin class.

    } // Captcha_Registration_Form

    To put the class to action, we need to instantiate it like so:

    new reCAPTCHA_Login_Form();

    Wrap Up

    If you wish to use the plugin on your WordPress site or to study the code, download the plugin from my GitHub repository.

    This is the third in a series that demonstrates how the WordPress HTTP API can be used in a plugin to consume APIs.

    Be sure to keep an eye on the WordPress channel for similar tutorials.

    Happy coding!

    Frequently Asked Questions (FAQs) on Integrating a CAPTCHA with the WordPress Registration Form

    How Can I Add a CAPTCHA to My WordPress Registration Form?

    Adding a CAPTCHA to your WordPress registration form is a simple process. First, you need to install and activate a CAPTCHA plugin. There are several plugins available, such as Google Captcha (reCAPTCHA) or Really Simple CAPTCHA. Once the plugin is activated, navigate to the settings page and configure the plugin as per your requirements. After configuring, you can add the CAPTCHA to your registration form by using the shortcode provided by the plugin.

    Why Should I Use a CAPTCHA on My WordPress Registration Form?

    CAPTCHA is a security measure that helps protect your website from spam and abuse. It does this by verifying that the user is a human and not a bot. By adding a CAPTCHA to your WordPress registration form, you can prevent automated bots from creating fake accounts, thus enhancing the security of your website.

    What Types of CAPTCHA Can I Use on My WordPress Registration Form?

    There are several types of CAPTCHA that you can use on your WordPress registration form. These include text CAPTCHA, image CAPTCHA, audio CAPTCHA, and Google reCAPTCHA. Each type has its own advantages and disadvantages, so you should choose the one that best suits your needs.

    Can I Customize the Appearance of the CAPTCHA on My WordPress Registration Form?

    Yes, you can customize the appearance of the CAPTCHA on your WordPress registration form. Most CAPTCHA plugins provide options for customizing the look and feel of the CAPTCHA. You can change the color, size, and style of the CAPTCHA to match your website’s design.

    How Can I Test If the CAPTCHA on My WordPress Registration Form Is Working Correctly?

    To test if the CAPTCHA on your WordPress registration form is working correctly, you can try registering a new account on your website. If the CAPTCHA is working correctly, you should be asked to complete the CAPTCHA challenge before you can submit the registration form.

    What Should I Do If the CAPTCHA on My WordPress Registration Form Is Not Working?

    If the CAPTCHA on your WordPress registration form is not working, you should first check if the plugin is properly installed and activated. If the plugin is working correctly, you should check the plugin settings to ensure that the CAPTCHA is correctly configured. If the problem persists, you may need to contact the plugin developer for assistance.

    Can I Use a CAPTCHA on Other Forms on My WordPress Website?

    Yes, you can use a CAPTCHA on other forms on your WordPress website. Most CAPTCHA plugins allow you to add a CAPTCHA to any form on your website, including contact forms, comment forms, and login forms.

    Does Adding a CAPTCHA to My WordPress Registration Form Affect User Experience?

    While adding a CAPTCHA to your WordPress registration form can enhance the security of your website, it can also affect the user experience. Some users may find it annoying to complete the CAPTCHA challenge. However, you can mitigate this by choosing a user-friendly CAPTCHA type, such as Google reCAPTCHA.

    How Can I Prevent Users from Bypassing the CAPTCHA on My WordPress Registration Form?

    To prevent users from bypassing the CAPTCHA on your WordPress registration form, you should ensure that the CAPTCHA is correctly configured and that it is required for form submission. Most CAPTCHA plugins provide options to make the CAPTCHA a required field.

    Can I Use a CAPTCHA on My WordPress Registration Form Without a Plugin?

    While it is possible to add a CAPTCHA to your WordPress registration form without a plugin, it requires a good understanding of PHP and WordPress development. If you are not comfortable with coding, it is recommended to use a plugin.