DEV Community

Cover image for How to Set Up Two-Factor Authentication on WordPress Without Plugin
Muhammad Usman
Muhammad Usman

Posted on • Originally published at pixicstudio.Medium

How to Set Up Two-Factor Authentication on WordPress Without Plugin

A step-by-step guide to add a 2-Factoe Authentication (2FA) system to your WordPress website.

Let’s walk through this code step-by-step. It adds a 2-Factor Authentication (2FA) system to a WordPress login. Think of it like a double-check for security — first your password, then a code sent to an admin’s email. Here’s how it works:

All you need to do is copy and paste this snippet to your functions.php file. But make sure to create your child theme first, so updating the theme won’t have any effect on the code.

Don’t want to add this snippet in your functions.php file? Don’t worry, just install a WPCode plugin and add this PHP snippet and activate it.

I have already tested this code on my sample project, it is working like a wonder.

// Step 1: Intercept Login Process and Redirect to 2FA Page
function custom_2fa_login_redirect($user, $password) {
    if (is_wp_error($user)) {
        return $user;
    }

    // Generate a random 6-digit code
    $two_fa_code = wp_rand(100000, 999999);
    update_user_meta($user->ID, '2fa_code', $two_fa_code);
    update_user_meta($user->ID, '2fa_code_time', time());

    // Get administrator email
    $admin_email = get_option('admin_email');

    // Send 2FA Code to Admin Email
    $subject = 'WordPress Login Verification Code';
    $message = "A login attempt was made. Your verification code is: " . $two_fa_code;
    wp_mail($admin_email, $subject, $message);

    // Store the user ID in a session to verify later
    set_transient('pending_2fa_user_' . $user->ID, $user->ID, 300); // Expires in 5 minutes

    // Redirect to a custom verification page
    wp_redirect(home_url('/wp-login.php?step=2fa&user_id=' . $user->ID));
    exit;
}
add_filter('authenticate', 'custom_2fa_login_redirect', 20, 2);

// Step 2: Show 2FA Code Input Field
function custom_2fa_login_form() {
    if (isset($_GET['step']) && $_GET['step'] == '2fa' && isset($_GET['user_id'])) {
        ?>
        <form method="post" action="<?php echo esc_url(home_url('/wp-login.php')); ?>">
            <p>
                <label for="2fa_code">Enter the verification code sent to the administrator email:</label>
                <input type="text" name="2fa_code" required>
            </p>
            <input type="hidden" name="user_id" value="<?php echo esc_attr($_GET['user_id']); ?>">
            <input type="submit" name="verify_2fa" value="Verify Code">
        </form>
        <?php
        exit; // Stop further execution of the default login form
    }
}
add_action('login_form', 'custom_2fa_login_form');

// Step 3: Verify 2FA Code
function verify_custom_2fa_code() {
    if (isset($_POST['verify_2fa']) && isset($_POST['user_id'])) {
        $user_id = intval($_POST['user_id']);
        $entered_code = sanitize_text_field($_POST['2fa_code']);
        $stored_code = get_user_meta($user_id, '2fa_code', true);
        $code_time = get_user_meta($user_id, '2fa_code_time', true);

        // Check if the code matches and is not expired (5 minutes validity)
        if ($entered_code === $stored_code && time() - $code_time <= 300) {
            delete_user_meta($user_id, '2fa_code'); // Remove used code
            delete_user_meta($user_id, '2fa_code_time');

            // Complete login
            wp_set_auth_cookie($user_id);
            wp_redirect(admin_url());
            exit;
        } else {
            wp_redirect(home_url('/wp-login.php?step=2fa&user_id=' . $user_id . '&error=invalid_code'));
            exit;
        }
    }
}
add_action('init', 'verify_custom_2fa_code');
Enter fullscreen mode Exit fullscreen mode

Step 1: Catch the Login & Send a Secret Code

When you try to log in, this code jumps in after you type your username/password. Here’s what happens:

  1. Generate a 6-digit code: It picks a random number using this logic $two_fa_code = wp_rand(100000, 999999) (like 123456) and saves it to your account’s profile.
  2. Email the code: It sends this code to the admin’s email address.
  3. Redirect you: Instead of letting you log in right away, it sends you to a verification page and says, “Hold on! Enter the code we just emailed!”

Why? This stops hackers — even if they guess your password, they’d need the code from the admin’s email to get in.

Step 2: Ask for the Code

Now you’re on the verification page. The code creates a simple form that says:

“Hey! Check the admin’s email and type the code”

You’ll see a box to type the code and a “Verify” button. Behind the scenes, it remembers which user is trying to log in (so it knows whose code to check later).

Step 3: Check if the Code is Correct

When you click “Verify,” the code does two important checks:

  1. Is the code right? It compares what you typed with the code it saved earlier.
  2. Is the code expired? The code only lasts 5 minutes. If you take too long, it’ll ask you to start over.

If both checks pass:

  • It logs you in and sends you to the WordPress dashboard.
  • It deletes the code (so it can’t be reused).

If something’s wrong:

  • It sends you back to the verification page with an error (like “Wrong code!” or “Code expired!”).

Why 2FA This Matters in your WordPress site?

  • Add an extra layer of security: Even if someone steals your password, they can’t log in without the code.
  • Very simple for users because: You just need to type a code that you have received to your email — no need for fancy apps or devices.
  • 5 Minutes temporary codes: Codes expire quickly in five minutes using this logic (set_transient(‘pending_2fa_user_’ . $user->ID, $user->ID, 300);), reducing the risk of hackers guessing them.

In Plain English / simple to understand

Imagine logging into your house:

  1. You unlock the first door (your login password).
  2. A guard (the code) stops you and says, “Prove it’s really you by showing me a secret note sent to your friend (administrator)!”
  3. Only after showing that note you get the access of the house.

That’s what this 2FA code snippet does for your WordPress site!

Let me know if you’d like to tweak anything — this is your security system, after all!

That’s a Wrap to this tutorial:

Thanks for reading to the end, and have a good day!
You rock! 🙌

Let’s grow, learn, and build amazing things together!
Don’t forget to give this guide a heart, save it to your list, and follow me.

Let’s stay friends! Stay connected with me on my other platforms:

LinkedIn | Medium| Bluesky

Top comments (0)