WordPress.org

Make WordPress Core

Opened 3 years ago

Last modified 10 months ago

#29889 new defect (bug)

Login redirect to login page even if authenticated

Reported by: sgissinger Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 3.9.2
Component: Login and Registration Keywords: reporter-feedback needs-testing close
Focuses: Cc:

Description

We use Wordpress in a private manner with use of login_redirect filter which is applied in the following code in file wp-login.php on line 777.

if ( empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) ) {
    if ( headers_sent() ) {
        $user = new WP_Error( 'test_cookie', sprintf( __( '<strong>ERROR</strong>: Cookies are blocked due to unexpected output. For help, please see <a href="%1$s">this documentation</a> or try the <a href="%2$s">support forums</a>.' ),
            __( 'http://codex.wordpress.org/Cookies' ), __( 'https://wordpress.org/support/' ) ) );
    } elseif ( isset( $_POST['testcookie'] ) && empty( $_COOKIE[ TEST_COOKIE ] ) ) {
        // If cookies are disabled we can't log in even with a valid user+pass
        $user = new WP_Error( 'test_cookie', sprintf( __( '<strong>ERROR</strong>: Cookies are blocked or not supported by your browser. You must <a href="%s">enable cookies</a> to use WordPress.' ),
            __( 'http://codex.wordpress.org/Cookies' ) ) );
    }
}

$requested_redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
/**
 * Filter the login redirect URL.
 *
 * @since 3.0.0
 *
 * @param string           $redirect_to           The redirect destination URL.
 * @param string           $requested_redirect_to The requested redirect destination URL passed as a parameter.
 * @param WP_User|WP_Error $user                  WP_User object if login was successful, WP_Error object otherwise.
 */
$redirect_to = apply_filters( 'login_redirect', $redirect_to, $requested_redirect_to, $user );

According to this, we use $user parameter in login_redirect filter to do some stuff.

Issue

After a first log in attempt with good credentials, $user is a WP_Error which isn't normal.
And when $user is a WP_Error my custom filter do redirect to login URL.

Then I try to log in a second time just after the first one with the same credentials.
In this second attempt, $user is a WP_User, my custom filter do not redirect to login URL and everything works as expected.

Additional Information

Complement 1

After the first login, if I reach home URL (which is very different from login URL), I notice that I was successfully authenticated even if I was redirected to login URL by my custom filter.

Complement 2

It seems to happen after my browser started, subsequent logins even with different credentials works fine at the first time.
If I restart my browser, this issue occurs and I'm redirected after first log in attempt.

Complement 3

Before our 3.9.2 update we were using 3.6.1 which handled this cookie check differently and did not overriden $user object.

Workaround

We completely commented these lines and everything now works fine even with my custom login_redirect filter.

Best

Change History (5)

#1 follow-up: @johnbillion
3 years ago

  • Keywords reporter-feedback added

Thanks for the report sgissinger. I'm unable to reproduce the problem you're experiencing. Note that the login_redirect filter is applied each time you view the login screen (even if you don't attempt to log in) in order to control where the redirect goes after the user does log in.

By default, the $user parameter in this situation is an empty WP_Error object. However, when you successfully log in the $user parameter will be a WP_User object.

Can you confirm that the bug still exists with the default theme activated and all other plugins deactivated? Also note that your callback function hooked into login_redirect shouldn't actually perform the redirect, it should just return the redirect location (but I think you're doing that anyway).

#2 in reply to: ↑ 1 @sgissinger
3 years ago

Replying to johnbillion:

Thanks for the report sgissinger. I'm unable to reproduce the problem you're experiencing. Note that the login_redirect filter is applied each time you view the login screen (even if you don't attempt to log in) in order to control where the redirect goes after the user does log in.

By default, the $user parameter in this situation is an empty WP_Error object. However, when you successfully log in the $user parameter will be a WP_User object.

Can you confirm that the bug still exists with the default theme activated and all other plugins deactivated? Also note that your callback function hooked into login_redirect shouldn't actually perform the redirect, it should just return the redirect location (but I think you're doing that anyway).

Yes my custom login_redirect only returns a simple string nothing else.

But the WP_Error is not empty. I've done a var_dump and it's filled by elseif ( isset( $_POST['testcookie'] ) && empty( $_COOKIE[ TEST_COOKIE ] ) ) { condition.

I think I omit some information

We use a custom login URL set in the login_url filter which also returns only a simple string.
This login URL only do the following (don't ask why please, it's a stupid reasaon but we do not have the choice )

echo file_get_contents("https://{$_SERVER['HTTP_HOST']}/extranet/wp-login.php");

Our WP is configured with multisite using the following cookie/login configuration

define('WP_ALLOW_MULTISITE', true);
define('MULTISITE',          true);

define('SUBDOMAIN_INSTALL',    false);
define('DOMAIN_CURRENT_SITE',  'www.example.com');
define('PATH_CURRENT_SITE',    '/extranet/');

define('FORCE_SSL_ADMIN', true);
define('FORCE_SSL_LOGIN', true);

define('SITECOOKIEPATH',  '/');
define('COOKIEPATH',      '/');

We use / for cookie pathes because we integrate WP auth in custom projects located in pathes different from /extranet.

#3 @sgissinger
3 years ago

I just tested with IE11 and Chrome37.

On the first access, wordpress_test_cookie is not set as it should be.
Once this cookie set everything works fine which looks like a confirmation of what I supposed earlier in this ticket.

In wp-login.php file on line 425, the following code must always set the wordpress_test_cookie, there no exclusive conditions and headers do not seem to have been sent.

//Set a cookie now to see if they are supported by the browser.
setcookie(TEST_COOKIE, 'WP Cookie check', 0, COOKIEPATH, COOKIE_DOMAIN);
if ( SITECOOKIEPATH != COOKIEPATH )
	setcookie(TEST_COOKIE, 'WP Cookie check', 0, SITECOOKIEPATH, COOKIE_DOMAIN);

Beside that, Wordpress successfully set cookies named wp-settings-1 and wp-settings-time-1 on the first access.

#4 @chriscct7
2 years ago

  • Keywords needs-testing added

#5 @swissspidy
10 months ago

  • Keywords close added
Note: See TracTickets for help on using tickets.