Skip to content

Instantly share code, notes, and snippets.

@devkabir
Created January 14, 2025 11:24
Show Gist options
  • Select an option

  • Save devkabir/6ed9e794a6e66bdaf0a59fc04dc30f6d to your computer and use it in GitHub Desktop.

Select an option

Save devkabir/6ed9e794a6e66bdaf0a59fc04dc30f6d to your computer and use it in GitHub Desktop.
google recaptcha plugin
<?php
/**
* Plugin Name: Google reCAPTCHA for Login
* Description: A simple plugin to add Google reCAPTCHA to the WordPress login form.
* Version: 1.0.0
* Author: CodeCraft Guide
* Text Domain: google-recaptcha-login
* Domain Path: /languages
* License: GPL2
*/
defined( 'ABSPATH' ) || exit; // Prevent direct access.
// Define constants.
define( 'GRL_PLUGIN_VERSION', '1.0.0' );
define( 'GRL_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
class GoogleRecaptchaLogin {
/**
* Constructor to initialize hooks and settings.
*/
public function __construct() {
add_action( 'admin_init', [ $this, 'register_settings_fields' ] );
add_action( 'login_enqueue_scripts', [ $this, 'enqueue_recaptcha_script' ] );
add_action( 'login_form', [ $this, 'add_recaptcha_to_login_form' ] );
add_filter( 'authenticate', [ $this, 'exclude_other_filters' ], 1, 3 );
}
/**
* Ensure only the custom reCAPTCHA callback executes on the authenticate hook.
*
* @param WP_User|WP_Error|null $user The current user or WP_Error object if authentication failed.
* @param string $username The username used for authentication.
* @param string $password The password used for authentication.
*
* @return WP_User|WP_Error The modified user object or WP_Error.
*/
public function exclude_other_filters( $user, $username, $password ) {
if ( empty( $user ) || empty( $username ) || empty( $password ) ) {
return;
}
global $wp_filter;
// Save the original authenticate filter callbacks.
$original_callbacks = [];
if ( isset( $wp_filter['authenticate'] ) ) {
foreach ( $wp_filter['authenticate']->callbacks as $priority => $callbacks ) {
foreach ( $callbacks as $callback ) {
if ( ! is_array( $callback['function'] ) && 0 === strpos( $callback['function'], 'wp_' ) ) {
$original_callbacks[ $priority ][ $callback['function'] ] = $callback;
}
}
}
}
// Remove all other callbacks for the 'authenticate' filter.
remove_all_filters( 'authenticate' );
// Add only your callback.
add_filter( 'authenticate', [ $this, 'verify_recaptcha_response' ], 10, 3 );
// Execute your callback.
$user = apply_filters( 'authenticate', $user, $username, $password );
// Restore original callbacks.
if ( ! empty( $original_callbacks ) ) {
$wp_filter['authenticate']->callbacks = $original_callbacks;
}
return $user;
}
/**
* Enqueue the Google reCAPTCHA script.
*/
public function enqueue_recaptcha_script() {
$site_key = $this->get_site_key();
if ( empty( $site_key ) ) {
return; // Site key not set, do nothing.
}
wp_enqueue_script(
'google-recaptcha',
'https://www.google.com/recaptcha/api.js',
[],
null,
true
);
}
/**
* Add reCAPTCHA to the login form.
*/
public function add_recaptcha_to_login_form() {
$site_key = $this->get_site_key();
if ( empty( $site_key ) ) {
return; // Site key not set, do nothing.
}
echo '<div class="g-recaptcha" data-sitekey="' . esc_attr( $site_key ) . '"><strong>reCAPTCHA by CodeCraft Guide</strong></div>';
}
/**
* Verify reCAPTCHA response after form submission.
*
* @param WP_User|WP_Error $user The user or WP_Error object if authentication failed.
* @param string $username The username used for authentication.
* @param string $password The password used for authentication.
* @return WP_User|WP_Error
*/
public function verify_recaptcha_response( $user, $username, $password ) {
if ( ! isset( $_POST['g-recaptcha-response'] ) || empty( $_POST['g-recaptcha-response'] ) ) {
return;
}
$response = sanitize_text_field( wp_unslash( $_POST['g-recaptcha-response'] ) );
$secret_key = $this->get_secret_key();
if ( empty( $secret_key ) ) {
return $user; // Allow login if secret key is not set (fail silently).
}
$response_data = wp_remote_post( 'https://www.google.com/recaptcha/api/siteverify', [
'body' => [
'secret' => $secret_key,
'response' => $response,
'remoteip' => $_SERVER['REMOTE_ADDR'] ?? '',
],
] );
if ( is_wp_error( $response_data ) || empty( $response_data['body'] ) ) {
dump( $response_data->get_error_message() );
return new WP_Error( 'recaptcha_error', $response_data->get_error_message() );
}
$result = json_decode( $response_data['body'], true );
if ( empty( $result['success'] ) || true !== $result['success'] ) {
return new WP_Error( 'recaptcha_error', __( 'reCAPTCHA verification failed. Please try again.', 'google-recaptcha-login' ) );
}
return $user;
}
/**
* Get the Google reCAPTCHA site key.
*
* @return string
*/
private function get_site_key() {
return get_option( 'grl_recaptcha_site_key', '' );
}
/**
* Get the Google reCAPTCHA secret key.
*
* @return string
*/
private function get_secret_key() {
return get_option( 'grl_recaptcha_secret_key', '' );
}
/**
* Register settings fields for reCAPTCHA keys.
*/
public function register_settings_fields() {
// Register settings.
register_setting( 'general', 'grl_recaptcha_site_key', [
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'default' => '',
] );
register_setting( 'general', 'grl_recaptcha_secret_key', [
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'default' => '',
] );
// Add settings fields.
add_settings_field(
'grl_recaptcha_site_key',
__( 'reCAPTCHA Site Key', 'google-recaptcha-login' ),
[ $this, 'render_site_key_field' ],
'general'
);
add_settings_field(
'grl_recaptcha_secret_key',
__( 'reCAPTCHA Secret Key', 'google-recaptcha-login' ),
[ $this, 'render_secret_key_field' ],
'general'
);
}
/**
* Render the reCAPTCHA Site Key field.
*/
public function render_site_key_field() {
$site_key = get_option( 'grl_recaptcha_site_key', '' );
printf(
'<input type="text" id="grl_recaptcha_site_key" name="grl_recaptcha_site_key" value="%s" class="regular-text" />',
esc_attr( $site_key )
);
echo '<p class="description">' . esc_html__( 'Enter your Google reCAPTCHA site key.', 'google-recaptcha-login' ) . '</p>';
}
/**
* Render the reCAPTCHA Secret Key field.
*/
public function render_secret_key_field() {
$secret_key = get_option( 'grl_recaptcha_secret_key', '' );
printf(
'<input type="text" id="grl_recaptcha_secret_key" name="grl_recaptcha_secret_key" value="%s" class="regular-text" />',
esc_attr( $secret_key )
);
echo '<p class="description">' . esc_html__( 'Enter your Google reCAPTCHA secret key.', 'google-recaptcha-login' ) . '</p>';
}
}
// Initialize the plugin.
new GoogleRecaptchaLogin();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment