25

After searching for a couple of days and reading 2 year old threads I'm having difficulty finding a solution to the problem of having users login by email only.

At first I was delighted to see WP_Email_Login only to find out you can still use your username to login. I'm not sure how to go about writing this as a plugin. My idea is to override the register_new_user function. I didn't see this on the "pluggable" functions list. Can I use filters/action do accomplish this?

I realize it's not fashionable to edit the core files so I'm hoping a solution is out there however if one does not exist I'll take my chances. In the first line of the "register_new_user" function in wp-login.php I can add:

$nickname_variable(??) = $user_login // set the nickname to the username
$user_login = $user_email; // set the user_login/username to the email address

This works quite nicely since WordPress doesn't allow people to change their username. In the Register Screen (form) it asks for the Username & Email; I'd like to set the Username to the Nickname variable (if someone can tell me what the nickname variable is called or where it's set during registration that'd be appreciated).

Cheers,

Smith

6
  • Are you trying to do away with usernames entirely? Why won't the Email Login plugin work for you?
    – Ryan
    May 9, 2012 at 22:40
  • I'm really curious why you'd want to do away with usernames, since those are the basis of all user information in WordPress. It's a bit like trying to do away with Posts - a lot of work for not a lot of payoff, and a guarantee of issues down the road.
    – SickHippie
    May 9, 2012 at 23:00
  • 1
    @Ryan- I don't think I'll be able to get rid of usernames so instead I'm just forcing the username to equal the email address. May 10, 2012 at 6:29
  • @SickHippie - for login I think email is better and more unique than a username. I'd rather use the username as the nickname when the user posts. You're right it would be a pain to get "rid" of the variable "username" which is why I am not. I'm just choosing the username for the user when they register (username will be their email address; their nickname will be what they entered as their username). In the end no variables are lost everything is intact. May 10, 2012 at 6:34
  • 1
    @SickHippie - You're right since Wordpress's default is not to allow user's to change their username their username/email address would remain the same even if they were to change their contact email address. I've considered that from the beginning and in my own experience I have found that people rarely "delete" an email address. They may get new ones but typically they'll still have their old ones. And if not perhaps in those rare circumstances we'll manually change it in the database. I do really appreciate your feedback & insight SickHippie! Now I hope for a solution to my post :) May 13, 2012 at 6:43

9 Answers 9

25

Update: I have created a plugin for login, registration and retrieve password with email. https://wordpress.org/plugins/smart-wp-login/

Answer in short, you can configure WordPress to login with email.

Three Steps:

  • Remove default authentication function
  • Add custom authentication function
  • Change text "Username" in wp-login.php to "Email"

One Note:

  • Don't edit core files.

Remove WordPress default authentication function.

WordPress uses "authenticate" filter to perform additional validation at user login.

remove_filter('authenticate', 'wp_authenticate_username_password', 20);

Add custom authentication function

add_filter('authenticate', function($user, $email, $password){

    //Check for empty fields
    if(empty($email) || empty ($password)){        
        //create new error object and add errors to it.
        $error = new WP_Error();

        if(empty($email)){ //No email
            $error->add('empty_username', __('<strong>ERROR</strong>: Email field is empty.'));
        }
        else if(!filter_var($email, FILTER_VALIDATE_EMAIL)){ //Invalid Email
            $error->add('invalid_username', __('<strong>ERROR</strong>: Email is invalid.'));
        }

        if(empty($password)){ //No password
            $error->add('empty_password', __('<strong>ERROR</strong>: Password field is empty.'));
        }

        return $error;
    }

    //Check if user exists in WordPress database
    $user = get_user_by('email', $email);

    //bad email
    if(!$user){
        $error = new WP_Error();
        $error->add('invalid', __('<strong>ERROR</strong>: Either the email or password you entered is invalid.'));
        return $error;
    }
    else{ //check password
        if(!wp_check_password($password, $user->user_pass, $user->ID)){ //bad password
            $error = new WP_Error();
            $error->add('invalid', __('<strong>ERROR</strong>: Either the email or password you entered is invalid.'));
            return $error;
        }else{
            return $user; //passed
        }
    }
}, 20, 3);

Change text "Username" in wp-login.php to "Email"

We can use gettext filter to change text "Username" to "Email" without editing core files.

add_filter('gettext', function($text){
    if(in_array($GLOBALS['pagenow'], array('wp-login.php'))){
        if('Username' == $text){
            return 'Email';
        }
    }
    return $text;
}, 20);

I have also written a detailed article at my blog http://www.thebinary.in/blog/wordpress-login-using-email/

2
  • 2
    Nice answer Nishant Jun 12, 2014 at 16:21
  • useful! In my case I just strip email special characters and make it a username. so [email protected] becomes user_example_com and it worked.
    – wpcoder
    Apr 28, 2018 at 20:01
7

It's possible, you must change the default validation via the action filter.

// Remove the default filter.
remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );

// Add custom filter.
add_filter( 'authenticate', 'fb_authenticate_username_password', 20, 3 );
function fb_authenticate_username_password( $user, $username, $password ) {

    // If an email address is entered in the username box, 
    // then look up the matching username and authenticate as per normal, using that.
    if ( ! empty( $username ) )
        $user = get_user_by( 'email', $username );
    
    if ( isset( $user->user_login, $user ) )
        $username = $user->user_login;
    
    // using the username found when looking up via email
    return wp_authenticate_username_password( NULL, $username, $password );
}

An alternative is a public plugin.

3
  • Thanks for the reply however I'm not sure if you read my post or if I wasn't clear enough. I apologize for the latter. In my original post I mentioned WP_Email_Login plugin; the exact plugin your code and link is from. Here's my original post: "At first I was delighted to see WP_Email_Login only to find out you can still use your username to login." <--- See the problem I can still use a username so that's why this plugin will not work. Since I can't do away with usernames I'm thinking of overriding the register function by forcing the username to equal the email address. May 10, 2012 at 6:37
  • However I'm searching for a way to accomplish this without editing the core files. If it's not possible that's fine but I'd like to know either way. Thanks! May 10, 2012 at 6:41
  • this is a way without editing the core files. Copy the code in a plugin, activate and ready.
    – bueltge
    Apr 1, 2013 at 22:06
6

Using the above code:

// Change login credentials
// remove the default filter
remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
// add custom filter
add_filter( 'authenticate', 'my_authenticate_username_password', 20, 3 );
function my_authenticate_username_password( $user, $username, $password ) {

    // If an email address is entered in the username box, 
    // then look up the matching username and authenticate as per normal, using that.
    if ( ! empty( $username ) ) {
        //if the username doesn't contain a @ set username to blank string
        //causes authenticate to fail
        if(strpos($username, '@') == FALSE){
                $username = '';
            }
        $user = get_user_by( 'email', $username );
        }
    if ( isset( $user->user_login, $user ) )
        $username = $user->user_login;

    // using the username found when looking up via email
    return wp_authenticate_username_password( NULL, $username, $password );
} 

All we had to do was check that the provided username at-least looked like a email and if not sabotage the username.

1
  • 2
    Rather than the primitive string check for '@' in the username, Wordpress has a handy built-in function: sanitize_email will return either a valid email address format or nothing: sanitize_email('email¬!"@business_com'); // Returns nothing
    – indextwo
    Jul 7, 2014 at 10:16
1

Slight modifications to the code above should be all that is needed to create an elegant solution. The documentation for the authenticate hook states that either a WP_User object or WP_Error object should be returned.

The source code for the wp_authenticate_username_password function runs through some pretty simple checks; we can just replicate the way those checks are done, and create a new WP_Error object to deal with the email address. Alternatively, we could even jack the wp_authenticate_username_password code and modify it if we wanted, although that seems unnecessary unless you really want to customize how things function. The code below should do the trick: (Although I haven't tested it myself...)

// Remove the default authentication function
remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );

// Add the custom authentication function
add_filter( 'authenticate', 'custom_authenticate_username_password', 20, 3 );

function custom_authenticate_username_password( $user, $username, $password ) {

    // Get the WP_User object based on the email address
    if ( ! empty( $username ) ) {
        $user = get_user_by( 'email', $username );
    }

    // Return a customized WP_Error object if a WP_User object was not be returned (i.e. The email doesn't exist or a regular username was provided)
    if ( ! $user ) {
        return new WP_Error( 'invalid_username_email', sprintf( __( '<strong>ERROR</strong>: Invalid username. Please log in with your email address. <a href="%s" title="Password Lost and Found">Lost your password</a>?' ), wp_lostpassword_url() ) );
    }

    // Hand authentication back over to the default handler now that we a have a valid WP_User object based on the email address
    return wp_authenticate_username_password( null, $username, $password );
}
1

it is already in WP-CORE!

now wordpress already allows to register EMAIL as username. but if you are talking about already registered users, then try the listed answers.

1
  • 1
    A link to the WP documentation where this is explained would be so useful. Could you provide it? I haven't had any luck while searching for it. Apr 26, 2021 at 11:39
1

I know this is quite an old topic but it comes up in google quite highly, so thought I'd sling in an answer.

Since 4.5.0 Wordpress has wp_authenticate_email_password (docs) which is hooked onto the authenticate filter.

So, to only allow email auth, you just have to remove the username auth as seen in other answers:

remove_filter('authenticate', 'wp_authenticate_username_password', 20, 3);

That should be all you need.

0

I have been struggling to do this without coding and many of the proposed plugins here are not supported anymore. I found this one which does the job: https://wordpress.org/plugins/login-customizer/.

It also does other stuff, but it's still very lightweight.

1
  • Hello, and thank you for contributing to WPSE. On the whole, we aim for code or development answers rather than plugin recommendations. May 8, 2021 at 17:11
0

There's a plugin for that: Force Email Login

https://wordpress.org/plugins/force-email-login/

It's also on Github: https://github.com/miya0001/force-email-login

1
0

Change the field type as text in to email, so that the field will thrown an error if user tried to enter the username and password and hit the login

<input type="email" name="username" id="username" autocomplete="username" value="<?php echo ( ! empty( $_POST['username'] ) ) ? esc_attr( wp_unslash( $_POST['username'] ) ) : ''; ?>" />

buttonenter image description here

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.