I want to create a function that will halt the login process in wordpress and let a user to validate an otp form or code before he logins in fully. And i intend this interception to be just after the users email and password

This is what i tried

add_filter( 'authenticate', 'smyles_check_custom_auth', 10, 3 );

function smyles_check_custom_auth( $user, $username, $password ){
    $otp_check = 'bad';  // variable returned from query but just using bad for testing
    if( !$otp_check == 'good' ){
          return confirm_form();
    elseif($otp_check == 'good'){
        return $user;
    return new WP_Error( __( 'OTP Check failed' ) );

Yet it did not work out, it only stops the form from validating without any error message shown if i set my priority at 20,3

My goal is to allow the username and password to get validated first, and then the submit button and the username and password field will be disabled and my confirm otp code will been shown, once the user confirms the right otp he then the login process continues which is the redirect process hopefully to the admin. If i set the priority level to 10, 3 the form gets submitted and user logins in no matter what code i have.

Workflow is this:

  1. User puts his usernme and password
  2. Wp_ authenticate () if user name and password match a user in wp_users table
  3. If it matches then mycustom send otp to the user email() is called.
  4. Wp Disable username and password boxes or field filter is called.
  5. mycustom confirmotp() is called which is a simple html form to collect entered otpcode.
  6. Mycustom verify () checkes the otpcode and return various errors like digit , is numeric, it not matche errors.
  7. But if the returned value from my otpvalidation query is true or okay, then...
  8. Wp redirect to wpdmin is called which is part of the wpsignon process.

So all my problem is to know a hook that i can hook in my otp confirm _form() so it executed after user name and password authication but before the action wpsignon() is called. Just a middle interception.

  • Whats your code so far?
    – Johnny97
    Sep 14, 2020 at 19:59
  • There's an official 2FA plugin on the .org repository, intended to be merged in the future into WordPress itself, you should look into it. However, it's not clear what your question is, which part of the implementation are you unsure about? There are a lot of requirements and specifications in your question but you need too clearly state the question unambiguously
    – Tom J Nowell
    Sep 14, 2020 at 20:13
  • I have viewed two step otp source code and is really confusing to me, i don't know which filters they are using, but you get the clue of what i want to archive, similar to two factor otp process, just that i use my own otp forms and confirmation process, just to hook it in.
    – chris
    Sep 16, 2020 at 4:04

1 Answer 1


Yes there is an authenticate filter you can hook into in the wp_authenticate function, and return a WP_Error if the login fails.

 * Filters whether a set of user login credentials are valid.
 * A WP_User object is returned if the credentials authenticate a user.
 * WP_Error or null otherwise.
 * @since 2.8.0
 * @since 4.5.0 `$username` now accepts an email address.
 * @param null|WP_User|WP_Error $user     WP_User if the user is authenticated.
 *                                        WP_Error or null otherwise.
 * @param string                $username Username or email address.
 * @param string                $password User password
$user = apply_filters( 'authenticate', null, $username, $password );

This is exactly how WordPress internally validates username and password, these are the default filters used:

add_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
add_filter( 'authenticate', 'wp_authenticate_email_password', 20, 3 );
add_filter( 'authenticate', 'wp_authenticate_spam_check', 99 );

I recommend setting your filter to priority of 10, or something less than 20 (which is when username/password is checked), so your check is ran first.

If your test passes, just return the first variable passed, for example:

add_filter( 'authenticate', 'smyles_check_custom_auth', 10, 3 );

function smyles_check_custom_auth( $user, $username, $password ){
    $otp_check = false;
    if( $otp_check ){
        return $user;
    return new WP_Error( __( 'OTP Check failed' ) );
  • Thanks alot @sMyles you pointed me in the right direction, so i fail the process in the place as to echo my custom form, then once the otp is confirmed i will then return $user?
    – chris
    Sep 15, 2020 at 1:49
  • Secondly this $user, $password or $username used in the function parameters are they global variables? Or i can use if isset to actually get the variables entered by the user in the user login form?
    – chris
    Sep 15, 2020 at 1:51
  • sorry i tested your code and it didnt work, and i have equally updated my question using your code and nothing works, i need guide please
    – chris
    Sep 15, 2020 at 16:06
  • @chris no you don't echo ANYTHING, you either return the $user variable on success or a WP_Error on failure
    – sMyles
    Sep 15, 2020 at 21:57
  • @chris this is why you should be detailed when opening a question, because your edit is now completely different than what your original question was, and it sounds like you don't have any kind of OTP handling integrated yet, which your original question eluded to the fact that you did.
    – sMyles
    Sep 15, 2020 at 22:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.