Forum Replies Created

Viewing 7 replies - 1 through 7 (of 7 total)
  • Thread Starter jacopol

    (@jacopol)

    Yes I’ll go with the $wpdb methods since it’s the only way this is stable. I’m replicating the sanitization and filters from wp_insert_user() so I should be safe. Also, the endpoint is never exposed publicly and it’s only accessed by the AWS Lambda that is triggered by users purchasing a product, so the environment where all this happens should be relatively controlled. Also considering I do all the checks on application password and what not way before the user insertion is ever needed.

    For the few filters I’m skipping, I checked and nothing is really done on those, except for wp_pre_insert_user_data of course, where TML does the password hashing. Since I take explicit care fo the hashing myself, everything should be good.

    Thank you for your help! I’ll update here if I ever manage to fix this without the current workaround.

    Thread Starter jacopol

    (@jacopol)

    Regarding the unexplained password hashing. Theme my login has this filter:

    function tml_ms_filter_pre_insert_user_data( $data = array() ) {
    	if ( tml_allow_user_passwords() && ! empty( $_POST['user_pass1'] ) ) {
    		$data['user_pass'] = wp_hash_password( $_POST['user_pass1'] );
    	}
    	return $data;
    }

    that is hooked to wp_pre_insert_user_data. So I guess that explains it.

    Thread Starter jacopol

    (@jacopol)

    One thing I don’t understand, about the possible explanations related to the corrupted state of Theme My Login and the issue with the hashed password: How are these only affecting the requests sent from my AWS Lambda (in my staging website)? The cached Theme My Login state is not depending on the HTTP request source and the password is internally generated by the plugin, so completely independent from the HTTP request.

    Thread Starter jacopol

    (@jacopol)

    No worries, I appreciate your help with this and don’t expect you to read back at all the previous messages.

    Just as quick recap:
    1. Production website: plugin always broken, independently from request source. Request from local machine broke and no theme or plugin was updated since the last working request sent from local machine.
    2. Staging website: plugin works only if request is sent from my local machine. Different theme wrt production site, but that shouldn’t matter because of 1. Plugins are synced to the production site.

    I had some insightful back and forth with my host’s support. They worked on my staging website.

    There was an idea about some corrupted state of the Theme My Login plugin I’m using to handle registration. The state of the plugin was, allegedly, reset by the host support, but it only worked for the first request sent from my AWS Lambda, and broke again right at the second one. Now it’s back to the same behaviour described in 2.

    The only stable solution I found is to directly run the query to add new users to my users and usermeta tables via wpdb::query. I will add the checks done by wp_insert_user() to ensure the fields are properly sanitized, but I will skip the filters. Those are hard to track and seems to be the only source of issue here.

    I’m not sure what skipping those filters entitles, I’m no expert WP developer at all, but I’ll try to read a bit more about it and act accordingly.

    Thread Starter jacopol

    (@jacopol)

    This is what I’m using to print for debugging. I added conditions to directly check what the if case causing the error is evaluating.

    add_filter( 'wp_pre_insert_user_data', function( $data ) {
      error_log( print_r( $data, true ) );
      error_log( is_array($data) ? 'is array' : 'is NOT array' );
      error_log( empty($data) ? 'is empty' : 'is NOT empty' );
    }, PHP_INT_MAX );

    This is what’s printed

    [04-Feb-2024 20:40:57 UTC] Array
    (
        [user_pass] => $P$B6jXtADMIdzWpoij5dafcvqfLLgJxy0
        [user_nicename] => jacopoprovaprova-com
        [user_email] => [email protected]
        [user_url] => 
        [user_registered] => 2024-02-04 20:40:52
        [user_activation_key] => 
        [display_name] => Jacopo Prova
        [user_login] => [email protected]
    )
    
    [04-Feb-2024 20:40:57 UTC] is array
    [04-Feb-2024 20:40:57 UTC] is NOT empty

    So everything looks correctly composed to me, and, as long as my host is not doing some custom development over the WP open source code, I don’t see how that if case is triggering the error.

    As I mentioned, my staging website still works when the request is arriving from my local machine. My staging website uses a different theme (the standard Twenty* one) while my production uses the Intentionally Left Blank theme, since I use Oxygen builder that overwrites it. The plugin on my production website broke (for requests coming from my local machine) with the theme not changing since the plugin was working, so I don’t think the issue is related to the theme. But I can do some more test there.

    On my local WP installation my plugin works. Also there I have the Twenty* theme (although a different one). Unfortunately my host doesn’t provide access to wp-includes/ so I don’t have a way to check if any custom code was added to the open source WP installation. I contacted them regarding the issue and I’m waiting for an answer.

    The API endpoint I’m using is a custom one I added. I have some custom tables I add rows to when receiving the POST request, so my plugin (listening to the custom endpoint) takes care of everything. In some cases, depending on the body of the request, I have to add the new user. So it was easier to just call wp_insert_user() instead of invoking the WP REST API just for that.

    Thank you for the password hint. I simply used wp_generate_password() assuming is was compatible. It’s not important since the password is just a place holder.

    Thread Starter jacopol

    (@jacopol)

    Thank you for your answer.

    My local machine is based in Sweden, while the AWS is in the US. I guess that could explain any block based on location?

    The security is entirely handled by my host, and I don’t have access to the config files. The host also uses Jetpack, but I got the same behaviour with Jetpack deactivated, so I don’t think that’s the cause of the problem.

    As you suggested I tried with PHP_INT_MAX in the filter and I got the same results. I also made sure empty( $data ) and is_array( $data ) are returning the correct values with the intercepted $data.

    On my staging website, that has all the plugins in sync with my main production website (where I’m getting the issue), I can still submit successfully the request from my local machine, although the AWS doesn’t work there either.

    As you suggested, all this kind of makes me think there is some weird blocks my host is using, for security reasons, on programmatic user insertion. I initially was thinking of differences in encoding (or something similar) that somehow broke $data, but if intercepting it with PHP_MAX_INT gives a correctly composed array, the issue must not be in my plugin.

    Thread Starter jacopol

    (@jacopol)

    Thank you for you answer. Which kind of poorly considered security measure are you thinking about?
    Trying again tonight gives the same error even when sending the request from my local machine. Not a step forward, but makes more sense.

    Since this is how the wp_insert_user() looks like when giving that error

    	$data = apply_filters( 'wp_pre_insert_user_data', $data, $update, ( $update ? $user_id : null ), $userdata );
    
    	if ( empty( $data ) || ! is_array( $data ) ) {
    		return new WP_Error( 'empty_data', __( 'Not enough data to create this user.' ) );
    	}

    I tried to intercept $data right before calling wp_insert_user() with this

    add_filter( 'wp_pre_insert_user_data', function( $data ) {
       error_log( print_r( $data, true ) );
    }, 20 );

    and the printout looks reasonable and definitely not empty

    [user_pass] => $P$BNIhibiz/od63ARGcF5NfjAKEVHaxV0
    [user_nicename] => johndoejohndoe-com
    [user_email] => [email protected]
    [user_url] =>
    [user_registered] => 2024-02-01 20:26:07
    [user_activation_key] =>
    [display_name] => John Doe
    [user_login] => [email protected]

    I tried to add the missing fields (user_url and user_activation_key) but it made no difference.

Viewing 7 replies - 1 through 7 (of 7 total)