Support » Developing with WordPress » wp_set_current_user, wp_set_auth_cookie to programmatically login user dont work

  • I’m using these two functions as outlined in the WP Codex to programmatically login users for a sort of SSO for a client site. But it is not actually logging them in. The return value of wp_set_current_user() is a correct WP_User object. But nothing actually changes on the front end.

    if ( !is_user_logged_in() ) {
                    $user_login = 'kayla';
    
                    $user = get_user_by( 'slug', $user_login );
                    $user_id = $user->ID;
                    
                    wp_set_current_user($user_id, $user_login);
                    wp_set_auth_cookie($user_id);
                    do_action('wp_login', $user_login, $user, false);
                }  

    Above is a chunk of my code I’m using to login the user after they’ve been validated. It’s exactly as the documentation states. What is wrong?

Viewing 9 replies - 1 through 9 (of 9 total)
  • Moderator bcworkz

    (@bcworkz)

    Where is your code executed? If it’s too early it will fail to work. If the WP user/password can be utilized in your authentication, or the login form is modified to also collect the data that you need, you should use the “authenticate” filter to manage authentication. Then WP will login the user as it normally would without you needing to do anything else.

    I’m using something like this to create a sort of SSO for some client sites: https://wordpress.stackexchange.com/questions/58906/create-api-for-single-sign-on-with-3rd-party-site

    So there is no login form. Username (no pw) is being sent from one site to another to an endpoint I’ve created.

    Moderator bcworkz

    (@bcworkz)

    I did a quick test since that post that’s the source of your code looked pretty old. Your code at least still works for conventional HTTP requests when executed from a callback to the “init” action. If it does not work for REST requests, something else is going on. I’m assuming you have other code confirming the security token from the third party site is valid before doing an auto-logon.

    If your code does not even work for you for regular HTTP requests, it’s executed either too early, too late, or other code is somehow interfering. As I said, it works for me from the init action.

    Yes everything happens from the init function:

    add_action('init', 'add_endpoint', 0);
    function add_endpoint(){
                add_rewrite_rule('^api/sso/?(.+)?/?','index.php?ssoapi=1&token=$matches[1]','top');
    }
    add_action('parse_request', 'check_api', 0);
    function check_api() {
                global $wp;
    
                if(isset($wp->query_vars['ssoapi'])) {
                    handle_request();
                    exit;
                }
            }
    function handle_request(){
                global $wp;
    
                $token = $wp->query_vars['token'];
                $shared_secret = 'foobar';
    
                /*if((time() - $timestamp) > 30) 
                {
                    send_response('expired token');
                }
    
                $token = md5($shared_secret.$token);
                $token_to_check = esc_attr($_GET);
    
                if($token == $token_to_check)*/
    
                if ( !is_user_logged_in() ) {
                    $user_login = 'kayla';
    
                    $user = get_user_by( 'slug', $user_login );
                    $user_id = $user->ID;
                    
                    $curr = wp_set_current_user($user_id, $user_login);
                    error_log(print_r($curr,true));
                    wp_set_auth_cookie($user_id);
                    do_action('wp_login', $user_login, $user, false);
                } 
            }

    All the code executes fine – each function is being reached. Even $curr outputs the right user object. But nothing is actually happening on the front end afterwards.

    Moderator bcworkz

    (@bcworkz)

    handle_request() is essentially being called from “parse_request”, not “init”. That’s too early. Instead, try adding handle_request() as a callback to “init” within check_api() only if $wp->query_vars['ssoapi'] is set.

    BTW, adding a rewrite rule during every request from any frequent action like “init” is very poor practice and unnecessary. For one, by itself it has no effect. You also need to flush rewrite rules to actually effect change. Two, flushing rules is computationally very expensive. Three, rules, once activated by flushing rules, are persistent.

    To add any particular rule, either hook something that generally only runs once, like a plugin activation hook, then add and flush; or add it from arbitrary, temporary code, then visit the permalinks setting screen. This visit flushes the rules when you leave the page.

    Hmm I changed my check_api() function to use an action for handle_request and I’m still not getting logged in. handle_request() isn’t firing at all now – no matter what I put for a priority for the action..

    function check_api() {
                global $wp;
    
                if(isset($wp->query_vars['ssoapi'])) {
                    add_action('init', 'handle_request');
                    exit;
                }
            }
    Moderator bcworkz

    (@bcworkz)

    Uh-oh 🙁 That means I have the order reversed. My apologies. “parse_request” is too late, not too early. After double checking the source code, we can see that the user validation occurs between “init” and “parse_request”, so “init” has to be the operative action. Of course there are no query vars established at this point, so depending on the ‘ssoapi’ query var will not work. You’ll need to hook “init” and extract whatever part of the request is passed to establish that query var in order to decide what to do.

    I don’t know if it’s related, but I don’t understand why you would exit after handle_request(). Login requests generally redirect somewhere just prior to exit, but I don’t see any redirect happening. When “parse_request” fires, that indicates some content is being requested beyond simply logging in. By exiting, this request would not be fulfilled.

    Maybe this is fine with your setup, in which case it doesn’t matter if I don’t understand. But if you continue having issues once the login is resolved, you should consider if exiting is appropriate.

    Thanks for your help. I’m not totally sure it’s a timing issue – since I’ve always been able to reach the handle_request() that’s calling wp_set_current_user() and wp_set_auth_cookie(). But they’re not working as expected.

    Regardless, I did change my hooks around so that handle_request is called from init.

    add_action('init', 'check_api', 1);

    function check_api() {
         //global $wp;
    
         if(isset($_REQUEST['ssoapi'])) {
           handle_request($_REQUEST['token']);
           // exit;
         }
    }
    function handle_request($token=''){
        global $wp;
    
        $shared_secret = 'foobar';
    
        if ( !is_user_logged_in() ) {
            $user_login = 'kayla';
    
            $user = get_user_by( 'slug', $user_login );
            $user_id = $user->ID;
            
            wp_set_current_user($user_id, $user_login);
            wp_set_auth_cookie($user_id, true);
            do_action('wp_login', $user_login, $user, false);
            error_log(print_r(wp_get_current_user(),true));
        } 
    }

    This is a section of my code. I am getting to the logging in portion. However that last error log is logging a correct user object. But when I refresh the page I’m still logged out. I don’t understand why.

    If I remove the conditional from check_api() and just flat out call handle_request() and load the site directly, it will log me in.

    But I’m trying to do a SSO where this info is being sent from another one of the client’s sites through a curl request when they login on the other site. Is there something blocking from actually logging me in. Every function is being properly executed. Regardless of where the request is coming from, it’s all tied to init, which is getting hit. I have not seen other people have issues with this.

Viewing 9 replies - 1 through 9 (of 9 total)
  • The topic ‘wp_set_current_user, wp_set_auth_cookie to programmatically login user dont work’ is closed to new replies.