Reset Password failed in WP 4.1
Was working fine on 4.0 until i upgraded to 4.1. Reset password always return wrongkey
I feared this would happen, it should be an easy fix btw. I'll check it out asap
wp_login on 4.1 (line 580) is checking $_POST rp_key from front end reset form. That's the difference.
can you check the version I just committed, the changes are in the login page, I blind coded but theoretically it should work :)
I tried the same fix before, the reset password key doesn't pull out like it should on login page. I just tried yours and not working.
However, if one were to pass as the key as querystring on login_init and parse on login page as rp_key, it works. The question is how safe to resend key as querystring back on reroute reset password form? if ( $action == 'rp' || $action == 'resetpass' ) { $rp_cookie = 'wp-resetpass-' . COOKIEHASH; if ( isset( $_COOKIE[ $rp_cookie ] ) && 0 < strpos( $_COOKIE[ $rp_cookie ], ':' ) ) { list( $rp_login, $rp_key ) = explode( ':', wp_unslash( $_COOKIE[ $rp_cookie ] ), 2 ); $key = $rp_key; wp_redirect( home_url('/login/?action=resetpass&key='.$key) ); } else wp_redirect( home_url('/login/?action=resetpass') ); exit; }
Have you tried to put my code at the very beginning of the login page? It is possible that the rp_cookie is removed on page load. If that still doesn't work I would set the rp_cookie instead before the wp_redirect, and kill it as soon as the login page is loaded.
I did and not working
On Dec 25, 2014, at 2:16 AM, Matteo Spinelli [email protected] wrote:
Have you tried to put my code at the very beginning of the login page? It is possible that the rp_cookie is removed on page load. If that still doesn't work I would set the rp_cookie instead before the wp_redirect, and kill it as soon as the login page is loaded.
— Reply to this email directly or view it on GitHub.
From what I can tell the reason is that the path in the cookie (4th parameter) is set to wp-login.php so the cookie isn't accessible to the frontend script. Not sure how to get around this though!
good catch. I need to check the security implication of sending the rp_cookie around
I have got wordpress 4.0 but neither do I can access to the cookie 'wp-resetpass-' . COOKIEHASH.
I put this in the resetpasswordform:
$rp_cookie"; echo ""; I this is shown is the output: wp-resetpass-40370c1e89cda2df031ef1356b174bb1 Array ( [wordpress_test_cookie] => WP Cookie check [PHPSESSID] => 5fd21aea12baee66c195a145bad889c8 ) I cannot see the cookie "wp-resetpass" so the reset password feature it does not work.
The fast solution is to modify wp-login.php, around line 570 and 577.
setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
by
setcookie( $rp_cookie, $value, 0, '/', COOKIE_DOMAIN, is_ssl(), true );
Note: I am working in a development scenario with this home url, http://XXX.XXX.XXX.XXX/foo/wordpress_folder
Anybody have a solution that doesn't involve modifying WP core? My site is only small and I know all the users personally so they've been emailing me when they lose their password but it's starting to get a bit frustrating!
yes, you have to pass the $_COOKIE[ $rp_cookie ] as a parameter to the form. So far that is the only alternative I could think of
Thank you cubiq, do you plan to fix this on the code? I don't understand in a first view the solution.
have to check security implications, I don't have much time right now, but I will as soon as possible
Never mind, it works again in 4.1.1 - they must have decided it was a bad idea!
YES! gotta revert to previous version
Hi,
I'm currently experiencing issues with the error handling of wrong password reset keys. Could it be that in Wordpress 4.2 the cookie verification is added back in? At the moment I don't get the 'error' parameter in the URL, and therefore it redirects to the success page where the user is able to change add the new password. Which eventually won't work I guess (haven't tested it yet, because I have finished that page), because the key is invalid and posted in that form as well.
I did divide the code over multiple pages, so that might also be the issue. So I'm not sure the problem is in this code, but I'm wondering if someone is also experiencing issues with Wordpress 4.2.
Thanks!
Edit:
I did a little more research, and I could fix the problem by doing the following: In the function 'cubiq_login_init' I replaced the following:
// redirect to change password form
if ( $action == 'rp' || $action == 'resetpass' ) {
wp_redirect( home_url('/login/?action=resetpass') );
exit;
}
// redirect from wrong key when resetting password
if ( $action == 'lostpassword' && isset($_GET['error']) && ( $_GET['error'] == 'expiredkey' || $_GET['error'] == 'invalidkey' ) ) {
wp_redirect( home_url( '/login/?action=forgot&failed=wrongkey' ) );
exit;
}
With:
if ( $action == 'rp' ) {
$rp_cookie = 'wp-resetpass-' . COOKIEHASH;
list( $rp_login, $rp_key ) = explode( ':', wp_unslash( $_COOKIE[ $rp_cookie ] ), 2 );
$user = check_password_reset_key( $rp_key, $rp_login );
if ( ! $user || is_wp_error( $user ) ) {
wp_redirect( home_url( '/login/?action=forgot&failed=wrongkey' ) );
exit;
} else {
wp_redirect( home_url('/login/?action=resetpass') );
exit;
}
}
~~This seems to work for me, and maybe for other people as well? I don't see any security implications at the moment. But it has been a long day for me, so maybe you see some things to improve. For now this is working in my local development website. It will still take a few weeks before this website is finished, so I'm curious about your opinions.~~
Edit 2: Some more testing showed that this does actually NOT work.. I think I've messed up my cookies while testing. Because I still have the issue where the cookie path isn't correct, so it isn't available on the 'add new password' and it won't validate.
Still hoping someone has the answer :)
Yes, mine is broken again now too. Will have a look when I get a moment...
I got it working again, but I don't know yet if I created a possible security issue. This is my login_init action right now:
function custom_login_init () {
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'login';
if ( isset( $_POST['wp-submit'] ) ) {
$action = 'post-data';
} elseif ( isset( $_GET['reauth'] ) ) {
$action = 'reauth';
} elseif ( isset($_GET['key']) ) {
$action = 'resetpass-key';
}
if ( $action == 'rp' || $action == 'resetpass-key' ) {
$rp_cookie = 'wp-resetpass-' . COOKIEHASH;
list( $rp_login, $rp_key ) = explode( ':', wp_unslash( $_COOKIE[ $rp_cookie ] ), 2 );
$user = check_password_reset_key( $rp_key, $rp_login );
if ( ! $user || is_wp_error( $user ) ) {
wp_redirect( home_url( '/login/?action=forgot&failed=wrongkey' ) );
exit;
} else {
wp_redirect( home_url('/login/?action=resetpass&key=' . $rp_key . '&login=' . $rp_login) );
exit;
}
}
if (
$action == 'post-data' || // don't mess with POST requests
$action == 'reauth' || // need to reauthorize
$action == 'resetpass-key' ||
$action == 'logout'
) {
return;
}
wp_redirect( home_url( '/login/' ) );
exit;
}
add_action('login_init', 'custom_login_init');
What I did is getting the cookie details and pass them around as a get parameter. This works, but I don't know if it is a security leak. One minor problem with this, is the path the cookie is set on. Therefore I can't view it on my custom page, because it is limited to /wp-login.php. That way I can't delete it after the reset is successful, and you get the 'wrong code' error if you try to reset it again after you've changed your password. This because WP still checks the cookie, and therefore the new key doesn't match the key in the cookie (and WP trusts the cookie). So I think there isn't a solution yet, other then change the path in the core, which isn't something we would do.
I've created a post in the WP forums, but haven't had a reply yet: https://wordpress.org/support/topic/custom-forgot-password-new-password-page-and-url?replies=1#post-6896822
Jeroen.
@JeroenReumkens I temporarily solved it like you did but in version 4.1.1 and It works. I'm not an expert but I can't find any security issues on passing the key as a get parameter. I'll try your solution on version 4.2 and let you know after testing it.
For me this solution is working in 4.2.1. But still I'm not satisfied with this solution. it feels a little bit 'hacky'. And if a user tries to reset its password two times in a row, it won't work. Although no one will probably do that.
Im having this problem right now. It didnt work on Wordpress 4.1 and it still doesnt work on 4.2.2 The fix JeroenReumkens suggested doesnt work. The only difference is that it then right away tells me the key has expired, instead of letting me fill in the two new password fields before telling me it has expired.
Does anyone know what actions i can take? The modification of wp-login.php didnt work either i might add.
Anyone have the slightest clue on what to do?...
Hello @joelthedangerous Did you try with this fix #4 ?
Hi @AntoineIM Thank you so much for your time. I tried it now. But after i click the reset password in the email-link and after i choose a new password, nothing happens. The page refresh and takes me to the normal login page with username and password. And the password doesnt seem to have changed.
Now i would give you more things to go on, but i dont understand the code at all and how wordpress reset password works. I have a hard time making progress at all.
This is my functions code atm, sorry in advance if the code markdown isnt corect, this is the first time i post code on github:
function cubiq_login_init ()
{
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'login';
if (isset( $_POST['wp-submit']))
{
$action = 'post-data';
}
else if (isset( $_GET['reauth']))
{
$action = 'reauth';
}
if ( $action == 'rp' || $action == 'resetpass' ) {
if (isset($_GET['key']) && isset($_GET['login']))
{
$rp_path = wp_unslash('/user/log-in/');
$rp_cookie = 'wp-resetpass-' . COOKIEHASH;
$value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) );
setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
}
wp_redirect( home_url('/user/log-in/?action=resetpass') );
exit;
}
if ($action == 'post-data' || $action == 'reauth' || $action == 'logout')
{
return;
}
wp_redirect( home_url( '/user/log-in/' ) );
exit;
}
add_action('login_init', 'cubiq_login_init');
Solved it!
If i removed the function in functions.php, followed the password reset link in the mail, was taken to wp-login standard page, and then did nothing, added the function again to functions.php and followed the reset password link in my mail and ended up on the front end login password reset, everything worked!
Now, if i didnt remove the function and only was taken to the front end login page, i still had the correct wp-resetpass- cookie with correct path, but i guess the cookie on the page wp-login.php doesnt get properly set. So the solution for me was to create a cookie in the function, at the same place you create the cookie for the front end reset.
Now my functions php looks like this:
function cubiq_login_init () {
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'login';
if ( isset( $_POST['wp-submit'] ) ) {
$action = 'post-data';
} else if ( isset( $_GET['reauth'] ) ) {
$action = 'reauth';
}
// redirect to change password form
if ( $action == 'rp' || $action == 'resetpass' )
{
if( isset($_GET['key']) && isset($_GET['login']) )
{
//Set the cookie for wp-login page
$wp_login_rp_path = wp_unslash('/wp-login.php');
$wp_login_value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) );
$wp_login_rp_cookie = 'wp-resetpass-' . COOKIEHASH;
setcookie( $wp_login_rp_cookie, $wp_login_value, 0, $wp_login_rp_path, COOKIE_DOMAIN, is_ssl(), true );
//set the cookie for front end login page
$front_end_rp_path = wp_unslash('/user/log-in/');
$front_end_value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) );
$front_end_rp_cookie = 'wp-resetpass-' . COOKIEHASH;
setcookie( $front_end_rp_cookie, $front_end_value, 0, $front_end_rp_path, COOKIE_DOMAIN, is_ssl(), true );
}
wp_redirect( home_url('/user/log-in/?action=rp') );
exit;
}
// redirect from wrong key when resetting password
if ( $action == 'lostpassword' && isset($_GET['error']) && ( $_GET['error'] == 'expiredkey' || $_GET['error'] == 'invalidkey' ) ) {
wp_redirect( home_url( '/user/log-in/?action=forgot&failed=wrongkey' ) );
exit;
}
if (
$action == 'post-data' || // don't mess with POST requests
$action == 'reauth' || // need to reauthorize
$action == 'logout' // user is logging out
) {
return;
}
wp_redirect( home_url( '/user/log-in/' ) );
exit;
}
add_action('login_init', 'cubiq_login_init');
where everything inside if( isset($_GET['key']) && isset($_GET['login']) ) is the new code.
I also changed all the $_GET["resetpass'] in login markup to just 'rp', like the standard wordpress parameter is. I dont know if that makes a difference.
couldn't one just remove the wp cookie and create a new one on '/' path? that should be read from anywhere.
I cant make that work. I removed and only used one cookie now with the path / and it complained about expired key, that is basically missing cookie. The below code does not work for me.
//Set the cookie for wp-login page
$wp_login_rp_path = wp_unslash('/');
$wp_login_value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) );
$wp_login_rp_cookie = 'wp-resetpass-' . COOKIEHASH;
setcookie( $wp_login_rp_cookie, $wp_login_value, 0, $wp_login_rp_path, COOKIE_DOMAIN, is_ssl(), true );
Maybe its a security thing in wordpress, the path must be /wp-login.php or something.
I tried fix #4, and this did actually work. In that pull request they create a new cookie (which I also did in my solution), but still I changed it to the / path instead of a specific url. This because I use two different pages for the forgot password and create new password page. The fix #4 doesn't have the bug I mentioned before, where the old cookie wouldn't be deleted. So for me, this works perfectly!
It still doesn't work. I'm at localhost – is this a problem? And I'm at WordPress 4.2.2.