• Resolved stezter

    (@stezter)


    This an excellent plug-in that has invaluable potential for me.

    I haven’t activated it permanently yet due to a simple concern …

    My main WordPress Admin is not a user in my external database. If the external database is not available for some reasons, how can admin log-in to WordPress? How can I ensure Administrators will always have access to the site irrespective of externalDB connection?

    Thanks
    Steve

Viewing 15 replies - 1 through 15 (of 24 total)
  • Hi Steve,

    I made my admin on the WordPress DB and the other db with external users. This way, you can access the site directly without needing access to the external DB.

    Also check the box in the External Login plugin to ensure that the WordPress DB will also login. I think the way Tom set it up is that WP db will always be present, so best to put your admin there.

    Thread Starter stezter

    (@stezter)

    Thanks Sovrgn

    I think I’m going to have to make a staging site. I’m terrified of locking myself out!

    Steve

    Thread Starter stezter

    (@stezter)

    I have now verified my fear.

    If a WP Administrator is NOT present in the external database then the plugin will not refer to the local WPdb to authenticate the user; the admin cannot get in.

    So if the external database is down for any reason, you are locked out of WordPress.

    I have tested with all setting variations and this seems to be the case.

    Advice appreciated.

    Steve

    Thread Starter stezter

    (@stezter)

    I have looked through previous threads and found exactly this issue in a different guise (“Problem with Migration Mode and admin user”, Logged by Pablo). This was a year or so ago and the problem was not resolved.

    The plugin describes its default behaviour being that it tries to authenticate against an external database and if that fails it will revert to the local WordPress database. It doesn’t do that. If the external authentication fails, you’re are stuffed and locked out of WordPress. That’s terrifying.

    Steve

    Thread Starter stezter

    (@stezter)

    Happy to pay for this fix.

    Plugin Author tbenyon

    (@tbenyon)

    Hey @stezter,

    Thanks for getting in contact and flagging this issue.

    Can you please double check that you haven’t got ‘disable local login’ ticked in the admin area.

    If it is not ticked the plugin SHOULD try to login on the external DB and then if it fails to connect, try to login using the WordPress DB.

    I believed this to be working but I will have time this weekend to try and replicate this and rectify the issue. I wonder if it’s the migration mode preventing this functionality for some reason.

    Keep me posted and I’ll get back to you at latest Sunday with an update.

    Thanks,

    Tom 🙂

    Plugin Author tbenyon

    (@tbenyon)

    I need to get on with my day job so can’t test now but had a quick look.

    I think it might be because of migration mode. I’ll check at the weekend but on the off chance you want to test this in the mean time I thought I’d share this.

    At the bottom of login/authenticate.php in the plugin folder there is this code:

    
                    // Hook that passes user data on successful login
                    do_action('exlog_hook_action_authenticated', $user, $exlog_userdata);
                }
            }
    
            // Whether to disable login fallback with the local WordPress version of the username and password
            // Prevents local login if:
            // - Disable local login  is set in the admin area
            // - OR
            // - The user was found but the password was rejected
            if (exlog_get_option('external_login_option_disable_local_login') == "on" || is_wp_error($user)) {
                remove_action('authenticate', 'wp_authenticate_username_password', 20);
            }
        }
    
        return $user;
    }
    
    if (exlog_get_option("external_login_option_enable_external_login") == "on") {
        add_filter('authenticate', 'exlog_auth', 10, 3);
    }
    

    I speculate that the issue may be fixed if you change it to:

    
                    // Hook that passes user data on successful login
                    do_action('exlog_hook_action_authenticated', $user, $exlog_userdata);
                }
            }
    
        }
    
        // Whether to disable login fallback with the local WordPress version of the username and password
        // Prevents local login if:
        // - Disable local login  is set in the admin area
        // - OR
        // - The user was found but the password was rejected
        if (exlog_get_option('external_login_option_disable_local_login') == "on" || is_wp_error($user)) {
            remove_action('authenticate', 'wp_authenticate_username_password', 20);
        }
    
        return $user;
    }
    
    if (exlog_get_option("external_login_option_enable_external_login") == "on") {
        add_filter('authenticate', 'exlog_auth', 10, 3);
    }
    

    Let me know if you try it 🙂

    • This reply was modified 3 years, 6 months ago by tbenyon.
    Thread Starter stezter

    (@stezter)

    Hi Tom

    Thanks for your input and suggestions.

    I am not in migration mode and do not have disable local Login set. For your info I am running WordPress 551 and PHP 7.3.

    I’ll take a look at your code snippet and see what I can achieve with it.

    Thanks
    Steve

    Thread Starter stezter

    (@stezter)

    Tom

    I did what you suggested but no change. I have dissected the exlog_auth function to the best of my ability and do seem to now have it working. Of course I could have broken the function in other ways. Can you check what I’ve done? It’s all just parenthesis towards the end of the function

    <?php
    function exlog_auth( $user, $username, $password )
    {
    $migration_mode = exlog_get_option(‘external_login_option_migration_mode’) == “on”;

    // If not in migration mode or you are in migration mode and the username isn’t in the WordPress DB
    if (!$migration_mode || ($migration_mode && !username_exists($username)))
    {

    // Make sure a username and password are present for us to work with
    if ($username == ” || $password == ”) return;

    $response = exlog_auth_query($username, $password);

    $roles = exlog_map_role($response[‘role’]);

    $block_access_due_to_role = true;
    foreach ($roles as $role)
    {
    if ($role != EXLOG_ROLE_BLOCK_VALUE)
    {
    $block_access_due_to_role = false;
    }
    }

    // If a user was found
    if ($response)
    {

    // If role is blocking user access
    if ($block_access_due_to_role)
    {
    $user = new WP_Error(‘denied’, __(“You are not allowed access”));
    }

    // If user was NOT authenticated
    else if (!($response[“exlog_authenticated”]))
    {
    // User does not exist, send back an error message
    $user = new WP_Error(‘denied’, __(“Invalid username or password”));
    }

    // 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’],
    );

    // If user does not exist
    if ($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);
    }
    else
    {
    $exlog_userdata[‘ID’] = $user->ID;
    add_filter(‘send_password_change_email’, ‘__return_false’); // Prevent password update e-mail
    wp_update_user($exlog_userdata);
    }

    $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);
    }
    }

    // Whether to disable login fallback with the local WordPress version of the username and password
    // Prevents local login if:
    // – Disable local login is set in the admin area
    // – OR
    // – The user was found but the password was rejected
    if (exlog_get_option(‘external_login_option_disable_local_login’) == “on” || is_wp_error($user))
    {
    remove_action(‘authenticate’, ‘wp_authenticate_username_password’, 20);
    }

    return $user;
    }

    if (exlog_get_option(“external_login_option_enable_external_login”) == “on”)
    {
    add_filter(‘authenticate’, ‘exlog_auth’, 10, 3);
    }

    }

    Thread Starter stezter

    (@stezter)

    I tell a lie Tom, it’s not working.

    An existing wp user can now login but an an external user with no wp account cannot.

    Aghhh!

    Plugin Author tbenyon

    (@tbenyon)

    No problem, will have a propper look at this at the weekend.

    I appreciate you keeping me posted on developments 🙂

    Plugin Author tbenyon

    (@tbenyon)

    Hey Steve,

    I’ve had a look into this to try and replicate. I switched my version of PHP and WordPress to the versions you mentioned and am still finding the functionality working.

    To test I’m stopping my docker container of the external database and then checking that I can no longer login with new external users that have not yet been copied to the local WordPress database.

    In this situation I can still login with my local admin user.

    NEW THOUGHT!

    There are two states that block local login as you can see from this code snippet:

    
            // Whether to disable login fallback with the local WordPress version of the username and password
            // Prevents local login if:
            // - Disable local login  is set in the admin area
            // - OR
            // - The user was found but the password was rejected
            if (exlog_get_option('external_login_option_disable_local_login') == "on" || is_wp_error($user)) {
    

    The first is if disable local login setting is checked, but you’ve checked that you haven’t got that active.

    The second is if an external user was found in your external database but the user does not match.

    The reason this logic is here is because if your user updates their password in the external database, and that user does exist when we come to try and authenticate in WordPress, we should prevent local login if their password was not validated.

    I wonder if you are connecting to the external database and the admin user that you’re trying to login with locally also exists in your external database with the same username?

    If this is not the case then the next step is for you to add some error logs that I provide throughout this file and you send me the result of what happens when you login so that we can start debugging what stage is not working for you.

    Let me know,

    Thanks,

    Tom

    Thread Starter stezter

    (@stezter)

    Thanks Tom

    I think we’re going to have to spit out some logs. The user admin doesn’t exist in the external database and in that scenario I cannot login to WP with the admin account. If I add the admin user to the external database I can.

    I have nothing set to disable local logins.

    Steve

    Plugin Author tbenyon

    (@tbenyon)

    Hey Steve,

    Please find below a complete copy of /external-login/login/authenticate.php.

    Could you please copy and paste this over the code that you currently have in that file. It’s indentical but with lots of logs.

    
    <?php
    function exlog_auth( $user, $username, $password ){
        $migration_mode = exlog_get_option('external_login_option_migration_mode') == "on";
        error_log(' - - - - - - - -  EXLOG DEBUG START - - - - - - - - ');
        error_log('--- Exlog - Check 1');
        error_log(var_export($migration_mode, true));
        error_log(var_export(username_exists($username), true));
        // If not in migration mode or you are in migration mode and the username isn't in the WordPress DB
        if (!$migration_mode || ($migration_mode && !username_exists($username))) {
    
            error_log('--- Exlog - Check 2');
            error_log(var_export(username_exists($username), true));
            error_log(var_export(username_exists($password), true));
            // Make sure a username and password are present for us to work with
            if ($username == '' || $password == '') return;
    
            $response = exlog_auth_query($username, $password);
            error_log('--- Exlog - Auth response');
            error_log(var_export($response, true));
    
            $roles = exlog_map_role($response['role']);
            error_log('--- Exlog - Roles');
            error_log(var_export($roles, true));
    
            $block_access_due_to_role = true;
            foreach ($roles as $role) {
                if ($role != EXLOG_ROLE_BLOCK_VALUE) {
                    $block_access_due_to_role = false;
                }
            }
    
            error_log('--- Exlog - Block access due to role?');
            error_log(var_export($block_access_due_to_role, true));
            // If a user was found
            if ($response) {
                error_log('--- Exlog - In user found');
                // If role is blocking user access
                if ($block_access_due_to_role) {
                    error_log('--- Exlog - In block acces due to role');
                    $user = new WP_Error('denied', __("You are not allowed access"));
    
                    // If user was NOT authenticated
                } else if (!($response["exlog_authenticated"])) {
                    error_log('--- Exlog - In Not authenticated');
                    // User does not exist, send back an error message
                    $user = new WP_Error('denied', __("Invalid username or password"));
    
                    // If user was authenticated
                } else if ($response["exlog_authenticated"]) {
                    error_log('--- Exlog - In 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
                    error_log('--- Exlog - User');
                    error_log(var_export($user, true));
    
                    $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'],
                    );
                    error_log('--- Exlog - Exlog user data');
                    error_log(var_export($user, true));
    
                    // If user does not exist
                    if ($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 - NEW user');
                        error_log(var_export($user, true));
                    } else {
                        error_log('--- Exlog - Update user');
                        error_log(var_export($user, true));
                        $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 - Setting roles');
                    $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);
                    }
    
                    error_log('--- Exlog - Call authenticated hook');
                    // Hook that passes user data on successful login
                    do_action('exlog_hook_action_authenticated', $user, $exlog_userdata);
                }
            }
    
            // Whether to disable login fallback with the local WordPress version of the username and password
            // Prevents local login if:
            // - Disable local login  is set in the admin area
            // - OR
            // - The user was found but the password was rejected
            error_log('--- Exlog - Should block local login?');
            error_log(var_export(exlog_get_option('external_login_option_disable_local_login') == "on" || is_wp_error($user), true));
            error_log(var_export(exlog_get_option('external_login_option_disable_local_login') == "on", true));
            error_log(var_export(is_wp_error($user), true));
            if (exlog_get_option('external_login_option_disable_local_login') == "on" || is_wp_error($user)) {
                error_log('--- Exlog - BLOCKING local login');
                remove_action('authenticate', 'wp_authenticate_username_password', 20);
            }
        }
    
        error_log(' - - - - - - - -  EXLOG DEBUG END - - - - - - - - ');
        return $user;
    }
    
    if (exlog_get_option("external_login_option_enable_external_login") == "on") {
        error_log(' - - - - - - - -  EXLOG DEBUG END - - - - - - - - ');
        add_filter('authenticate', 'exlog_auth', 10, 3);
    } else {
        error_log(' - - - - - - - -  EXLOG DEBUG PLUGIN NOT ACTIVATED!!! - - - - - - - - ');
    }
    
    

    I think I’m going to make a feature out of showing these logs soon to help with these situations.

    Could you then login in the situation that is not working. Finally look at your PHP error logs and share with me what came out between:

    error_log(' - - - - - - - - EXLOG DEBUG START - - - - - - - - ');
    and
    error_log(' - - - - - - - - EXLOG DEBUG END - - - - - - - - ');

    IMPORTANT!!! Please make sure of obfuscate private and personal data.

    We’ll get there 😛

    Tom

    • This reply was modified 3 years, 6 months ago by tbenyon.
    • This reply was modified 3 years, 6 months ago by tbenyon.
    Thread Starter stezter

    (@stezter)

    Here you go Tom.

    Extract trying to login when user does not exist in external database but does exist in local wordpress database. It clearly blocking the local login but that’s not what my settings say.

    [27-Oct-2020 21:39:19 UTC] – – – – – – – – EXLOG DEBUG START – – – – – – – –
    [27-Oct-2020 21:39:19 UTC] — Exlog – Check 1
    [27-Oct-2020 21:39:19 UTC] false
    [27-Oct-2020 21:39:19 UTC] 10
    [27-Oct-2020 21:39:19 UTC] — Exlog – Check 2
    [27-Oct-2020 21:39:19 UTC] 10
    [27-Oct-2020 21:39:19 UTC] false
    [27-Oct-2020 21:39:19 UTC] — Exlog – Auth response
    [27-Oct-2020 21:39:19 UTC] array (
    ‘valid’ => false,
    )
    [27-Oct-2020 21:39:19 UTC] PHP Notice: Undefined index: role in /home/mothertechco/dev/wp-content/plugins/external-login/login/authenticate.php on line 21
    [27-Oct-2020 21:39:19 UTC] — Exlog – Roles
    [27-Oct-2020 21:39:19 UTC] array (
    0 => ‘subscriber’,
    )
    [27-Oct-2020 21:39:19 UTC] — Exlog – Block access due to role?
    [27-Oct-2020 21:39:19 UTC] false
    [27-Oct-2020 21:39:19 UTC] — Exlog – In user found
    [27-Oct-2020 21:39:19 UTC] PHP Notice: Undefined index: exlog_authenticated in /home/mothertechco/dev/wp-content/plugins/external-login/login/authenticate.php on line 43
    [27-Oct-2020 21:39:19 UTC] — Exlog – In Not authenticated
    [27-Oct-2020 21:39:19 UTC] — Exlog – Should block local login?
    [27-Oct-2020 21:39:19 UTC] true
    [27-Oct-2020 21:39:19 UTC] false
    [27-Oct-2020 21:39:19 UTC] true
    [27-Oct-2020 21:39:19 UTC] — Exlog – BLOCKING local login
    [27-Oct-2020 21:39:19 UTC] – – – – – – – – EXLOG DEBUG END – – – – – – – –

Viewing 15 replies - 1 through 15 (of 24 total)
  • The topic ‘Bypass ExternalDB for WordPress Admin’ is closed to new replies.