Support » Plugin: External Login » Problem with Log In

  • Resolved raider1967

    (@raider1967)


    Hello,

    I have configured the plugin and successfully connecting to the external database.

    However, when I try to log in using user data from the external database I get the following error;

    Notice: Trying to get property ‘ID’ of non-object in /wp-content/plugins/external-login/login/authenticate.php on line 39 which is the line of code in Bold below.

    The user has obviously been found and authenticated but there appears to be no user object at this part of the process – there is even a comment in your code that says “Does not return a WP_User object 🙁”

    // If user was authenticated
    } else if ($response[“exlog_authenticated”]) {
    // External user exists, try to load the user info from the WordPress user table
    $userobj = new WP_User();
    $user = $userobj->get_data_by(‘login’, $response[‘username’]); // Does not return a WP_User object 🙁
    $user = new WP_User($user->ID); // Attempt to load up the user with that ID

    $exlog_userdata = array(
    ‘user_login’ => $response[‘username’],
    ‘first_name’ => $response[‘first_name’],
    ‘last_name’ => $response[‘last_name’],
    ‘user_pass’ => $password,
    ‘role’ => $roles[0],
    ‘user_email’ => $response[’email’],
    );

    Any ideas what might be the cause of this issue ?

    thank you
    RAY

Viewing 14 replies - 1 through 14 (of 14 total)
  • Plugin Author tbenyon

    (@tbenyon)

    Hey Ray (@raider1967),

    Apologies for the delayed response. Been busy at work.

    This is a new one to me. My first guess is that your not getting all the required data that WordPress deems necessary for a user. The first thing I’d ask you to check is that you’ve specified all the field mappings and they are correct in the external login settings.

    If this doesn’t work, the next step would be for you to modify the code block your talking about to get some additional logs.

    If you could modify this code in the plugin to get the additional logs and then share the information back with me here that’d be awesome.

    IMPORTANT

    • You probably don’t want to do this on your live site as real users data could end up in your logs.
    • Make sure you use a test user for sharing the logs with me as I don’t want you sharing any personal information in the forum
    
                } else if ($response["exlog_authenticated"]) {
                    // External user exists, try to load the user info from the WordPress user table
                    $userobj = new WP_User();
                    error_log('EXLOG START>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
                    error_log('EXLOG resp >>>>');
                    error_log(var_export($response, true));
                    $user = $userobj->get_data_by('login', $response['username']); // Does not return a WP_User object 🙁
                    error_log('EXLOG user >>>>');
                    error_log(var_export($user, true));
                    error_log('EXLOG END>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
                    $user = new WP_User($user->ID); // Attempt to load up the user with that ID
    

    Thanks,

    Tom 😊

    Hi Tom

    The log output on a test user is as below – it should be noted that the user info does get copied across to the WordPress Users table ok.

    The role ‘none’ has been mapped to ‘Subscriber’.

    All the other mappings are correct as far as I can tell.

    regards
    RAY

    [14-Apr-2020 09:33:00 UTC] EXLOG START>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    [14-Apr-2020 09:33:00 UTC] EXLOG resp >>>>
    [14-Apr-2020 09:33:00 UTC] array (
    ‘username’ => ‘fredbloggs’,
    ‘password’ => ‘$2b$10$8/fDuw.Of7wL584GFrBoV.hEnUHmoXToJR.N3HSlD5/OFA0iyys.G’,
    ‘first_name’ => ‘FRED BLOGGS’,
    ‘last_name’ => ‘SEV’,
    ‘role’ => ‘none’,
    ’email’ => ‘ray.debarr@gmail.com’,
    ‘exlog_authenticated’ => true,
    )
    [14-Apr-2020 09:33:00 UTC] EXLOG user >>>>
    [14-Apr-2020 09:33:00 UTC] false
    [14-Apr-2020 09:33:00 UTC] EXLOG END>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    [14-Apr-2020 09:33:00 UTC] PHP Notice: Trying to get property ‘ID’ of non-object in /wp-content/plugins/external-login/login/authenticate.php on line 47
    [14-Apr-2020 09:33:00 UTC] PHP Warning: Cannot modify header information – headers already sent by (output started at /wp-content/plugins/external-login/login/authenticate.php:47) in /wp-includes/pluggable.php on line 943
    [14-Apr-2020 09:33:00 UTC] PHP Warning: Cannot modify header information – headers already sent by (output started at /homepages/11/d461060611/htdocs/clickandbuilds/HandPickedResources/wp-content/plugins/external-login/login/authenticate.php:47) in /wp-includes/pluggable.php on line 944
    [14-Apr-2020 09:33:00 UTC] PHP Warning: Cannot modify header information – headers already sent by (output started at /wp-content/plugins/external-login/login/authenticate.php:47) in /wp-includes/pluggable.php on line 945

    Plugin Author tbenyon

    (@tbenyon)

    Apologies for the delayed response 🙂

    Sorry if this is too much information but by writing this all out may help you help me solve the problem if your technically minded but I’m mostly doing it to remind me of my thought process as I come back to look at this issue.

    So the code we’re looking at is basically the oldest in the plugin. It comes from the article I’ve credited as being the original source for the concept. I can see better ways of handling this whole section but until I finish the work on bettering testing I don’t want to make large changes to this core logic as there are over 1000+ users depending on it for authentication of their apps.

    I think that we can be happy that the following line is returning false:

    $user = $userobj->get_data_by('login', $response['username']); // Does not return a WP_User object 🙁
    This is because it cannot determine a user from your WordPress database. This means the user with the username ‘fredbloggs’ does not exist in your users table in the user_login field. However I believe you said it does so can you please double check this.

    The strange thing that I can’t replicate is that your code is throwing an error because the ID does not exist on the $user property but althought this is true, I’ve not had any other users report this error blocking their login.

    I was wondering if you’re running a very old version of PHP but I’m not sure.

    NEXT STEP:
    Can you please replace this code block where I have added a couple of extra safeguards that may allow your implementation to function. It is the whole else if block:

    
                } else if ($response["exlog_authenticated"]) {
                    // External user exists, try to load the user info from the WordPress user table
                    $userobj = new WP_User();
                    error_log('EXLOG START>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
                    error_log('EXLOG resp >>>>');
                    error_log(var_export($response, true));
                    $user = $userobj->get_data_by('login', $response['username']); // Does not return a WP_User object 🙁
                    error_log('EXLOG user >>>>');
                    error_log(var_export($user, true));
                    $user = false;
                    if ($user) {
                        $user = new WP_User($user->ID); // Attempt to load up the user with that ID
                    }
    
                    $exlog_userdata = array(
                        'user_login' => $response['username'],
                        'first_name' => $response['first_name'],
                        'last_name'  => $response['last_name'],
                        'user_pass'  => $password,
                        'role'       => $roles[0],
                        'user_email' => $response['email'],
                    );
    
                    // If user does not exist
                    if (!$user || $user->ID == 0) {
                        // Setup the minimum required user information
    
                        $new_user_id = wp_insert_user( $exlog_userdata ); // A new user has been created
    
                        // Load the new user info
                        $user = new WP_User ($new_user_id);
                        error_log('EXLOG HERE1');
    
                    } else {
                        $exlog_userdata['ID'] = $user->ID;
    
                        add_filter('send_password_change_email', '__return_false'); // Prevent password update e-mail
    
                        wp_update_user($exlog_userdata);
                        error_log('EXLOG HERE2');
    
                    }
    
                    $user->set_role($roles[0]); // Wipe out old roles
    
                    // Add roles to user if more than one
                    foreach ($roles as $role) {
                        $user->add_role($role);
                    }
    
                    // Hook that passes user data on successful login
                    do_action('exlog_hook_action_authenticated', $user, $exlog_userdata);
                    error_log('EXLOG END>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
                }
    

    Thank you for your patience,

    Tom 🙂

    Hi Tom

    Thank you for your response which was all very helpful as an explanation. I am a PHP developer myself so do have a good understanding of what your code is doing.

    First of all, the revised code that you sent me does partly correct the problem and the log in process works as expected on the first login. No errors are encountered and the user details are pushed into WP users table.

    However, if I log out and then log in a second time I get the following error.

    Undefined property: WP_Error::$ID in /wp-includes/class-wp-user.php on line 170

    To answer some of your queries in your email, I have been running these tests on a brand new installation of WordPress using PHP version 7.3.16 – it maybe that it’s because of the newer version of PHP instead of an old version that is causing this issue – I know I have had problems with other projects switching up from PHP 7.1 to 7.3.

    Yes, the following line of code is definitely returning false.

    $user = $userobj->get_data_by(‘login’, $response[‘username’]); // Does not return a WP_User object 🙁

    At this point in your code, would you expect the details of the user from the external database to have been copied into the WordPress database? It appears that the user within WordPress does not exist at this point in the timeline, however, when I check the WordPress users after the ID error has been encountered, the user has definitely been created and does exist correctly within WordPress. As yet I have been unable to discover what part of your code pushes the user details from the external database into the WordPress database.

    During that first log in process, I am assuming that your code checks the external database for the user details, which it obviously finds because the authentication is coming back as ‘true’, copy of the log below

    [18-Apr-2020 10:11:47 UTC] EXLOG response >>>>
    [18-Apr-2020 10:11:47 UTC] array (
    ‘username’ => ‘fredbloggs’,
    ‘password’ => ‘$2b$10$jZAJXrIUtoGZVQkGhCSdp.HyfWkgMsTEWFY5/Nwt2BaozFcYVRxlm’,
    ‘first_name’ => ‘FRED BLOGGS’,
    ‘last_name’ => ‘SEV’,
    ‘role’ => ‘none’,
    ’email’ => ‘fred.bloggs@gmail.com’,
    ‘exlog_authenticated’ => true,
    )

    In your original code you have a comment that says…..

    // External user exists, try to load the user info from the WordPress user table
    $userobj = new WP_User();

    What I don’t understand is if the external user exists, why would you then try to load the user from the WordPress database? I can only assume at this point in time that the user does not exist in WordPress, only in the external database

    If I trace out $userobj I get the following which appears to be a blank WP user which would be correct based upon your $userobj = new WP_User();

    [18-Apr-2020 10:11:47 UTC] EXLOG userobj >>>>
    [18-Apr-2020 10:11:47 UTC] WP_User::__set_state(array(
    ‘data’ =>
    (object) array(
    ),
    ‘ID’ => 0,
    ‘caps’ =>
    array (
    ),
    ‘cap_key’ => NULL,
    ‘roles’ =>
    array (
    ),
    ‘allcaps’ =>
    array (
    ),
    ‘filter’ => NULL,
    ‘site_id’ => 0,
    ))

    Once the process has been run that first time and the first ID error encountered, the user details are pushed over to WordPress so running the log in process a second time does then work because the code can then find the user within WordPress ok.

    Another issue that is confusing things is that within your plugin settings within WordPress I have ‘Disabled Local Login’ which suggests that your code would only then check the external database for the user and not check the WP database. However, this appears not to function correctly as the WP database is still being checked within your authentication code. I am unable to locate any part of that authrnication process that says ‘If Disabled Local Login’ then dont check the WP database. Obviously I may be missing something that does that elsewhere but at the moment I cant see that my local WP database is being excluded.

    Anyways, I hope the above may be of some use to you.

    To clarify, the revised code you send me does fix my initial issue and enables me to log in using an external database which then pushes those user details to the WP users table. However, a subsequent login fails with the error mentioned earlier.

    Again, if the ‘Disable Local Login’ is set as ON, should your process be checking the WordPress database – surely it would only check the external database and authenticate the user that way?

    Will await further insight from you on this.

    many thanks
    RAY

    Tom

    as a further follow up your revised code returns the following logs.

    [18-Apr-2020 10:59:23 UTC] EXLOG START>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    [18-Apr-2020 10:59:23 UTC] EXLOG resp >>>>
    [18-Apr-2020 10:59:23 UTC] array (
    ‘username’ => ‘fredbloggs’,
    ‘password’ => ‘$2b$10$jZAJXrIUtoGZVQkGhCSdp.HyfWkgMsTEWFY5/Nwt2BaozFcYVRxlm’,
    ‘first_name’ => ‘FRED BLOGGS’,
    ‘last_name’ => ‘SEV’,
    ‘role’ => ‘none’,
    ’email’ => ‘fred.bloggs@gmail.com’,
    ‘exlog_authenticated’ => true,
    )
    [18-Apr-2020 10:59:23 UTC] EXLOG user >>>>
    [18-Apr-2020 10:59:23 UTC] false
    [18-Apr-2020 10:59:23 UTC] EXLOG HERE1
    [18-Apr-2020 10:59:23 UTC] EXLOG END>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    I noticed in your revised code the following;

    $user = false;
    if ($user) {
    $user = new WP_User($user->ID); // Attempt to load up the user with that ID
    }

    By setting $user to false, it will never then attempt to run the following code…. $user = new WP_User($user->ID); ??

    thanks
    RAY

    Plugin Author tbenyon

    (@tbenyon)

    Hey Ray,

    That is a cock up on my part. I put the $user = false; in so I could quickly try to replicate the error you were seeing. That definitely needs removing!!! Apologies for wasting your time on this.

    It would be so much easier if we could screen share and resolve this together 😛 Unfortunately not allowed to under the forum rules 😛

    The development system uses Docker so it should be quick to try PHP 7.3 locally. I’ll be back! 😛

    Plugin Author tbenyon

    (@tbenyon)

    Yeah, reading your message again. If it’s working for the first time now, and you remove that cock up discussed above does it now start to work?

    Hi Tom

    Ok, yes I have now removed the $user = false line and that seems to rectify the issue completely.

    Using your revised code without that line in it, I am able to log in ok from the external database and then if I log out, I can log in again successfully without error.

    However, it still aeppears to be trying to use the WP user details even though I have disabled the local login in your plugin settings.

    As a test, I changed the user password in the external database and tried logging in again using the original password and then get an error as below

    Undefined index: role in /wp-content/plugins/external-login/login/authenticate.php on line 13

    If I use the new password, it logs in ok, assuming then that it is checking the external database.

    thanks
    RAY

    Tom,

    Is there a way to stop the user being created in the WP users table so that the plugin only ever authenticates from the external database ?

    RAY

    Plugin Author tbenyon

    (@tbenyon)

    Ok, so the real fix here is that I need to implement and publish those safeguards. I’ve added this on the project board for a new release.

    In regard to your new query regarding stopping a user being created, I think this is not the solution to your problem. To function properly, WordPress has got to have the user stored. However, you’ll notice there is a setting that disables local login. This prevents any user from logging in with the local DB and forces the use of the external one. 🙂

    I’ll mark this ticket as resolved for now, but if you have further issues, please don’t hesitate to get back in contact.

    If you don’t mind I’d be grateful if you could take the time to write a review or buy me a beer.

    Thanks Ray,

    Tom 😀

    Hi Tom

    I am aware of your setting that disables the local login, however as per previous posts this appears not to be working perhaps as it should.

    To explain again,

    As a test, I changed the user password in the external database and tried logging in again using the original password and then get an error as below

    Undefined index: role in /wp-content/plugins/external-login/login/authenticate.php on line 13

    If I use the new password, it logs in ok, assuming then that it is checking the external database.

    How can I avoid this error above if the user changes their password and then forgets and tries logging in with the old password?

    Of course, happy to leave a review / etc

    Will sort that oput shortly.

    thanks
    RAY

    Plugin Author tbenyon

    (@tbenyon)

    Hey Ray,

    Regarding the “Undefined index: role” I believe this is only a warning and not throwing an error but I may be wrong? This should not be displaying in the front end. If it is, you probably should make sure it doesn’t show these warnings on your production site.

    I think this is because you haven’t set up table mapping for the role field in for the external database in the External Login settings.
    We can test this is true by, setting it to a random field in your users table which should disregard this issue I think. Foe example, set it to the field that stores the username.

    To avoid this warning for the future I’ll also add some safeguards so that that data isn’t required.

    Unless I misunderstood you though it does sound like the functionality is working as you would expect?

    1. User logs in with correct password from external database and gains access
    2. user logs out
    3. password is changed in external database
    4. User tries to log in with old (incorrect) password in WP and does not get logged in
    5. User uses the new (correct) external password to login and gains access to WP

    Is this the flow you expected?

    Thanks Ray,

    Tom 🙂

    Hi Tom

    Ok yes you are right, it’s just a warning as I forgot to set WP_DEBUG back to false again.

    So yes the functionality flow is as you desribe now.

    Thank you for your assistance with this and for a great plugin. I will sort out Review / Beer shortly.

    regards
    RAY

    Plugin Author tbenyon

    (@tbenyon)

    Hey Ray,

    No problem! Glad you got it all set up!

    Well done 😊

    Good luck with the project!

    Tom

Viewing 14 replies - 1 through 14 (of 14 total)
  • You must be logged in to reply to this topic.