How To Secure Buddypress Ajax Tabs

Hi,

I have ajaxified my subnav menu as the page reload was ruining user experience (in my opinion).

It's first time I have done ajax for secured buddypress pages and not sure how to secure access.

To illustrate problem here is snippet of code:

function bp_legacy_theme_tab_template_loader() {
	// Bail if not a POST action
	if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) )
		return;

	// Sanitize the object
	$section = sanitize_title( $_POST['section'] );
	$tab = sanitize_title( $_POST['tab'] );

	// just doing members section but this would be expanded for all section
	$path = 'members/single/'.$section.'/'.$tab; // have to specify like this or menu is loaded twice

	// Locate the object template
	bp_get_template_part( $path );
	exit();
}

This code would be hooked onto ajax action. It just passes the section and tab to load.
In its current form it works fine for my small test and it loads my profile tabs nicely. However, there is no validation so any logged out user can modify the post and view the details of any page such as hidden profile fields or messages and the like.

To be honest I don't even know why my code works. How is it determining the current user? I tried on a few different profiles I set up and it works. I guess wordpress must set a referrer somewhere for ajax requests that buddypress reads.

What should I do to validate this so it doesn't show pages that should be hidden? I did some googling and nonces were suggested but that would not stop logged in users viewing other users pages that they should not be, it would just stop logged out users (I think).

Any help appreciated. I know I ask questions that are a bit more awkward than typical how to use a plugin stuff. I am really amazed at the great responses you guys give. Thanks in advance :slight_smile:

  • Adam Czajczyk

    Hey Mark,

    I hope you're well today!

    I've noticed that you mentioned nonces. This is definitely a good way to go regarding overall security of your site. Despite the fact that nonce will not provide you with a check for current user (on what a user can access and what can't) it's an absolute must.

    As for preventing users from seeing other users pages. Could you please elaborate a bit on this? I'd like to know how this code of yours should work, what should be accessible by the "current user" and what not. A short case scenario would be great!

    Please advise!

    Cheers,
    Adam

  • Mike

    Hi Adam,

    here is a use case:

    - User navigates to their profile page, defualt "view" tab is visible.
    - User clicks on edit tab. This triggers jquery function that posts "section: 'profile', tab:'edit'" to my code above through wordpress ajax url.
    - My code snippet locates the template part and returns the generated html
    - Jquery sets the viewpane with the new html

    This all works fine. The tab loads nicely without causing a full page load. However this scenario also works:

    - User navigates to someone elses profile page, defualt "view" tab is visible and nothing else.
    - User edits javascript in browser so that its posts "section: 'profile', tab:'edit'" to my code above through wordpress ajax url.
    - My code snippet locates the template part and returns the generated html
    - Jquery sets the viewpane with the new html and all profile fields (even hidden ones) are viewable.

    This is not that bad I guess but it would also be possible to do with messages and private groups after I expand the code to cover all sections sub tabs. I want to secure against this. To use a nonce it would have to link in with how buddypress is able to infer the context in an ajax query and I do not yet know how it does so. I am sure there is a really simple answer but I just can't think of it.

  • Hoang Ngo

    @Mike,

    I hope you are well today.

    If you want to use the wp_nonce, you will have to edit all the links or ajax parameters to include the nonce param. For create the wp_nonce, you can do something like this
    wp_create_nonce($section.$tab);
    Please note that, you will need to pass the $section & $tab base on your scenario.
    And then, in the code, you can try this

    function bp_legacy_theme_tab_template_loader() {
    	//this is use for user logged in
    	if ( ! is_user_logged_in() ) {
    		//if you don't want non logged in user to see the content, just return here
    		return;
    	}
    
    	// Bail if not a POST action
    	if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
    		return;
    	}
    
    	// Sanitize the object
    	$section = sanitize_title( $_POST['section'] );
    	$tab     = sanitize_title( $_POST['tab'] );
    
    	//verify the nonce
    	if ( ! wp_verify_nonce( $_POST['wpnonce'], $section . $tab ) ) {
    		return;
    	}
    
    	// just doing members section but this would be expanded for all section
    	$path = 'members/single/' . $section . '/' . $tab; // have to specify like this or menu is loaded twice
    
    	// Locate the object template
    	bp_get_template_part( $path );
    	exit();
    }

    Lets see if it can help :slight_smile:

    Best regards,
    Hoang

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.