0

I have a custom login form that I can display by adding [custom-login-form] to a static page. While the form does look rather different, it still submits its data via method="post" to wp_login_url() (with no parameters), as the default login form does.

I send users to the page via a plugin, like this:

add_action( 'login_form_login', array( $this, 'redirect_to_custom_login' ) ); // login
public function redirect_to_custom_login() {
    if ( 'GET' === $_SERVER['REQUEST_METHOD'] ) {
        if ( '' !== $this->redirect_after_login_url ) {
            $redirect_to = $this->redirect_after_login_url;
        } else {
            $redirect_to = null;
        }
        if ( is_user_logged_in() ) {
            $this->redirect_logged_in_user( $redirect_to );
            exit;
        }

        // The rest are redirected to the login page
        $login_url = site_url( 'user/login' );
        if ( ! empty( $redirect_to ) ) {
            $login_url = add_query_arg( 'redirect_to', $redirect_to, $login_url );
        }

        wp_redirect( $login_url );
        exit;
    }
}

I try to send non-admin users back to the page they were on after logging in, as well:

add_filter( 'login_redirect', array( $this, 'redirect_after_login' ), 10, 3 ); // login
public function redirect_after_login( $redirect_to, $requested_redirect_to, $user ) {
    $redirect_url = site_url();

    if ( ! isset( $user->ID ) ) {
        return $redirect_url;
    }

    if ( ! empty( $user->roles[0] ) && in_array( $user->roles[0], array( 'administrator' ) ) ) {
        // Use the redirect_to parameter if one is set, otherwise redirect to admin dashboard.
        if ( '' === $requested_redirect_to ) {
            $redirect_url = admin_url();
        } else {
            $redirect_url = $requested_redirect_to;
        }
    } else {
        // Non-admin users go to their account page after login, unless another url is supplied
        if ( '' === $requested_redirect_to ) {
            $redirect_url = site_url( 'user' );
        } else {
            $redirect_url = $requested_redirect_to;
        }
    }

    return wp_validate_redirect( $redirect_url, site_url() );
}

I'm also using the following code to try to keep users from being logged out:

if ( ! function_exists( 'custom_login_expiration' ) ) :
    add_filter( 'auth_cookie_expiration', 'custom_login_expiration' );
    function custom_login_expiration( $expirein ) {
        return 31556926; // 1 year in seconds
    }
endif;

But I'm getting consistent reports from multiple users that they have to keep logging in each day. I haven't had to do this myself, which is probably because I haven't been inactive for long enough. The reporting users are not administrators, but subscribers, contributors, editors, etc.

I can't see any evidence that my custom login hooks should have to set the cookie themselves - they don't seem to intercept that process, as far as I can tell - but I can't see out another reason that users would be logged out independently of the authorization expiration.

Update: I've discovered that admin level users are getting the proper cookies set, and thus they are able to stay logged in. But if a user is not sent to an admin page upon login, they do not get wp-settings-time-{user_id} and wp-settings-{user_id} cookies set.

I've tried a quick version of the wp_user_settings() method that Core uses to set these cookies. This does indeed set the expiration value, but it does not keep the user logged in when they close their browser.

function my_user_settings() {

    if ( is_admin() ) {
        return;
    }

    if ( ! $user_id = get_current_user_id() ) {
        return;
    }

    if ( ! is_user_member_of_blog() ) {
        return;
    }

    $settings = (string) get_user_option( 'user-settings', $user_id );

    if ( isset( $_COOKIE['wp-settings-' . $user_id] ) ) {
        $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user_id] );

        // No change or both empty
        if ( $cookie == $settings )
            return;

        $last_saved = (int) get_user_option( 'user-settings-time', $user_id );
        $current = isset( $_COOKIE['wp-settings-time-' . $user_id]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $user_id] ) : 0;

        // The cookie is newer than the saved value. Update the user_option and leave the cookie as-is
        if ( $current > $last_saved ) {
            update_user_option( $user_id, 'user-settings', $cookie, false );
            update_user_option( $user_id, 'user-settings-time', time() - 5, false );
            return;
        }
    }

    // The cookie is not set in the current browser or the saved value is newer.
    $secure = ( 'https' === parse_url( site_url(), PHP_URL_SCHEME ) );
    setcookie( 'wp-settings-' . $user_id, $settings, time() + YEAR_IN_SECONDS, SITECOOKIEPATH, null, $secure );
    setcookie( 'wp-settings-time-' . $user_id, time(), time() + YEAR_IN_SECONDS, SITECOOKIEPATH, null, $secure );
    $_COOKIE['wp-settings-' . $user_id] = $settings;
}

I thought I was on the right track with this part, and maybe I am, but it does not have the desired end result.

0

This is what I ended up adding to my plugin, and users report that it has been successful:

add_action( 'wp_login', array( $this, 'after_successful_login' ), 10, 2 );
/**
 * Make sure the auth cookie is set when a user logs in
 *
 * @param  string  $login   The user's username
 * @param  object  $user    The logged in user object
 *
 */
public function after_successful_login( $login, $user = '' ) {
    if ( ! ( $user instanceof WP_User ) ) {
        return;
    }
    /**
     * Log in a user by setting authentication cookies.
     *
     * @param  int   $user_id
     * @param  bool  $remember
     * @param  mixed $secure
     *
     */
    $remember = filter_var( get_option( $this->option_prefix . 'remember_user_login', false ), FILTER_VALIDATE_BOOLEAN );
    wp_set_auth_cookie( $user->ID, $remember, is_ssl() );
}

None of the replicating of wp_user_settings that I had tried above was necessary, just that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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