I have a WordPress website which I use just to populate blog posts and some private posts under custom post types. In another website, I am using the REST API to display the posts. If I use software like Postman, I can display data from the REST API.
How can I prevent any unauthorized REST API requests to domain www.example.com ? so if the request is not coming from www.mysite.com, it is blocked?
Basically prevent my custom post types (example.com) to be visible to the rest api if it is not coming from mysite.com
You can Disable External request by adding this in your wp-config.php ( Also, you can specify domain which you don't want to block like this).
define( 'WP_HTTP_BLOCK_EXTERNAL', TRUE );
define( 'WP_ACCESSIBLE_HOSTS', 'example.com, domain.com' );
apply_filters( 'rest_authentication_errors', WP_Error|null|bool )
Filters REST authentication errors.Put code in functions.php in your theme directory.
Complete description : https://developer.wordpress.org/reference/hooks/rest_authentication_errors/
add_filter( 'rest_authentication_errors', 'wpse150207_filter_incoming_connections' );
function wpse150207_filter_incoming_connections( $errors ){
$allowed_ips = array( '127.0.0.1' );
$request_server = $_SERVER['REMOTE_ADDR'];
if( ! in_array( $request_server, $allowed_ips ) )
return new WP_Error( 'forbidden_access', 'Access denied', array( 'status' => 403 ) );
return $errors;
}
One way to restrict REST requests is to hook at rest_api_init with priority 1, and whitelist the IP's you want. In this example, I restrict REST access to the server itself only:
/**
* Disables WordPress Rest API for external requests
*/
add_action('rest_api_init', function() {
$whitelist = ['127.0.0.1', "::1"];
if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
die('REST API is disabled.');
}
}, 1);
Related
I downloaded, installed and activated the plugin "JWT Authentication for the WP REST API".
And I see how I can obtain JWT access token when sending credentials from the client.
But I don't see how to use the plugin with the existing WordPress REST API.
For example, if I follow by the link like /wp-json/wp/v2/posts or /wp-json/wp/v2/posts/1, I still fetch the resource without any restricting the access, so the access is still public.
So how to restrict the access making it private with the plugin?
You can use the rest_authentication_errors hook filter to restrict the REST access coupled with is_user_logged_in() and user_can().
<?php
add_filter( 'rest_authentication_errors', function( $result ) {
if ( true === $result || is_wp_error( $result ) ) {
return $result;
}
if ( ! is_user_logged_in() && ! user_can( get_current_user_id(), 'export' ) ) {
return new WP_Error(
'rest_not_logged_in',
__( 'Silence is golden.' ),
array( 'status' => 401 )
);
}
return $result;
} );
I have a BuddyPress social networks in a multi network WordPress install (WordPress multisite), thanks to LH Buddypress Multi Network plugin.
How can I prevent people from accessing to a profile page from another blog?
For example :
teacherSite, teacherUser
studentSite, studentUser
I have restricted access to site for non-member.
teacherUser can only connect on teacherSite.
And he can’t see in the directory other users from others blogs.
If studentUser knows the teacherUser username or if he finds or tests…
He can go to:
studentSite.domain.com/members/teacherUser/
And he can see the profile of teacherUser even though teacherUser is not linked to studentSite.
Fortunately, there is no information (because everything else is well segregated) except the name and the gravatar.
But he can still make a connection request or send him a private message!
teacherUser will not see any notification on teacherSite. But he will potentially receive an email which will redirect him to studentSite without being able to connect to it.
How to avoid this?
I'm guessing BuddyPress has somewhat the same user management system as WordPress.
We could compare the current user role with the queried user role. If they're different, we block and redirect.
<?php
/**
* Compare the queried user role with the current user role.
* If both don't match restrict profile access and redirect to current user profile.
*
* Case exceptions:
* - IF the current user IS the queried user.
* - IF the current user IS an Admin or Super-Admin.
*/
add_action( 'wp', function() {
if ( is_author() && get_queried_object() instanceof \WP_User ) {
if ( reset( get_queried_object()->roles ) === reset( wp_get_current_user()->roles ) || get_current_user_id() === get_queried_object_id() || current_user_can( 'manage_options' ) ) { // ... #see https://wordpress.org/support/article/roles-and-capabilities/#capability-vs-role-table
return;
} else {
header( 'Refresh: 2; ' . esc_url( get_author_posts_url( get_current_user_id() ) ) );
$args = array(
'back_link' => true,
);
wp_die( "Error, Restricted access. You're not allowed to view this profile.", 'Error, Restricted access', $args );
};
};
} );
When you enable the function that allows anyone to register on your WordPress website, WordPress sends a link which looks like this:
<https://your-domain.com/wp-login.php?
action=rp&key=DFmJxTfZvqYQKJOAhBtA&login=Alice%20Cooper>
Unfortunately, some popular email providers, such as iCloud can't read <> tag properly. As a result, a visitor who is about to register on your website receives an error "Your password reset link appears to be invalid. Please request a new link below."
How could I force WordPress to remove this tag <...> in order to send the clear link?
P.s.: I know about the so-called "caching issues." In my case, I hope anyone might advice some add_action or another solution.
Filter the wp_mail function:
add_filter( 'wp_mail','remove_tags' );
function remove_tags( $args ){
$args['message'] = str_replace( '<', '', $args['message'] );
$args['message'] = str_replace( '>', '', $args['message'] );
return $args;
}
More information here: wp_mail.
How to get all admins of multisite in wordpress.
I am create custom plugin for this
I am stuck in custom code for get all the admins of multisite in main website.
for ex. my main website is : wyz.com and my second site is : xyz.com/demo.
main website admin is "abc" and for " xyz.com/demo" site admin is "abcde".
Now how i get "abcde" admin in my main website .
In my live site i have currently 6k admins. So i difficult to get this . I am new in multisite wordpress.
To get the data from any of the sub site, you first need to switch to that site using switch_to_blog() function. Then whatever the query you fire, it will give records from that site only. Don't forget to restore it to current site, once you get the data from sub-site. You can restore it using restore_current_blog() function.
To get the all admin users of all the sites, you need to perform the followings:
1) Use wp_get_sites() function to get the blog_id of all the sites.
2) Once you get the blog_id, You need to perform the following loop to get the admin user of each the sites.
Assume that you get $blog as array of blog_ids from wp_get_sites() function
foreach ($blogs as $blog)
{
switch_to_blog( $blog->blog_id ); // blog id which u got from wp_get_sites() function
$users_query = new WP_User_Query( array(
'role' => 'administrator',
'orderby' => 'display_name'
) ); // query to get admin users
$results = $users_query->get_results();
$site_admins .= 'Blog ID: ' . $blog->blog_id . '<pre>' . print_r($results,true) . '</pre>';
}
restore_current_blog();
Is it possible to access pluggin's data from WordPress database with some Rest API. I saw WP REST API but it doesn't give access to pluggin's data.
More specifically I use LearnDash pluggin and I want to access courses infos but they doesn't provide any API to access it.
Thanks
Overall you need to search Google for things having to do with "Wordpress rest api custom post type" and eventually you'll be dealing with registering custom post types and endpoints in your theme's functions.php
Here is the manual: https://developer.wordpress.org/rest-api/extending-the-rest-api
As an example, here is my situation: I'm using WordPress (4.7) and The Events Calendar ("TEC") plugin. I'm querying the WP DB from an Android app using the REST API, however the only data that's available to REST is basic WP post stuff. I need to expose the custom data in the TEC plugin to the REST API. In order to do that, I've included the following into my functions.php in my theme:
functions.php
/* Exposing the custom post type of the plugin to the REST API.
* In this case, for The Tribe Events Calendar plugin, the custom post type is
* "tribe_events". For other plugins it will be different. */
add_action( 'init', 'my_custom_post_type_rest_support', 25 );
function my_custom_post_type_rest_support() {
global $wp_post_types;
//be sure to set this to the name of your post type!
$post_type_name = 'tribe_events';
if( isset( $wp_post_types[ $post_type_name ] ) ) {
$wp_post_types[$post_type_name]->show_in_rest = true;
$wp_post_types[$post_type_name]->rest_base = $post_type_name;
$wp_post_types[$post_type_name]->rest_controller_class = 'WP_REST_Posts_Controller';
}
}
/* Exposing the custom taxonomy of the plugin to the REST API.
* In this case, for The Tribe Events Calendar plugin, the custom
* taxonomy is "tribe_events_cat". For other plugins it will be different.
*/
add_action( 'init', 'my_custom_taxonomy_rest_support', 25 );
function my_custom_taxonomy_rest_support() {
global $wp_taxonomies;
//be sure to set this to the name of your taxonomy!
$taxonomy_name = 'tribe_events_cat';
if ( isset( $wp_taxonomies[ $taxonomy_name ] ) ) {
$wp_taxonomies[ $taxonomy_name ]->show_in_rest = true;
// Optionally customize the rest_base or controller class
$wp_taxonomies[ $taxonomy_name ]->rest_base = $taxonomy_name;
$wp_taxonomies[ $taxonomy_name ]->rest_controller_class = 'WP_REST_Terms_Controller';
}
}
With the above in my functions.php, now I can query just the custom post type and taxonomy with the REST API. Here's a sample query:
http://www.mywebsite.com/wp-json/wp/v2/tribe_events?tribe_events_cat=64
However, I still don't see any of the custom plugin data per-event. All I see are the basic standard WP fields.
So now I have to add more to my functions.php:
/* Add specific endpoints to REST API.
* The TEC plugin has good documentation, and they have a
* list of the variables. With any other plugin, you might
* have to do more detective work. */
add_action( 'rest_api_init', 'slug_register_event_venue' );
function slug_register_event_venue() {
register_rest_field( 'tribe_events',
'_EventVenueID',
array(
'get_callback' => 'slug_get_event_venue',
'schema' => null
)
);
}
function slug_get_event_venue( $object, $field_name, $request ) {
$postId = tribe_get_venue_id( $object[ 'id' ]);
if ( class_exists( 'Tribe__Events__Pro__Geo_Loc' ) ) {
$output[ 'locid' ] = (float) $postId;
$output[ 'lat' ] = (float) get_post_meta( $postId, Tribe__Events__Pro__Geo_Loc::LAT, true );
$output[ 'lng' ] = (float) get_post_meta( $postId, Tribe__Events__Pro__Geo_Loc::LNG, true );
} else {
$output = array(
'locid' => 0,
'lat' => 0,
'lng' => 0,
);
}
return $output;
}
... and a bunch more endpoint definitions of which I'm excluding the code here.
Now when I run the same query from earlier, new data fields are present in the JSON: all of the endpoints I've added.
At this point I want to exclude a ton of things from the REST API output (all the miscellaneous WP stuff) and just return the event fields I'm interested in. To do that I just add a "&fields" parameter to my query, with fields seperated by comma. There's also a per_page and order parameters too.
http://www.mywebsite.com/wp-json/wp/v2/tribe_events?tribe_events_cat=64&per_page=100&order=asc&fields=id,title.rendered,_EventVenueID.lat,_EventVenueID.lng,_EventVenueID.locid,_EventStartDate.startdate,tribe_events_cat
This returns JSON data with only the data I'm interested in.
The TEC plugin maker has stated they'll be introducing official REST API support sometime soon. This means in the future I can probably eliminate all of this code in functions.php, and just utilize whatever interface the plugin maker comes up with... hopefully a nice sexy page inside the plugin settings.
Now that WP (4.7) has more or less a fully featured REST API, the ball is in the court of the plugin makers to build support for it. So this year you should see plugins be updated accordingly.
When you are creating the custom post type in WordPress just add one more parameter show_in_rest as true for the support the rest API for Custom post type.
/**
* Register a book post type, with REST API support
*
* Based on example at:
https://codex.wordpress.org/Function_Reference/register_post_type
*/
add_action( 'init', 'my_book_cpt' );
function my_book_cpt() {
$args = array(
'public' => true,
'show_in_rest' => true,
'label' => 'Books'
);
register_post_type( 'book', $args );
}
Please visit here.
Then you can use the custom endpoint by the URL like this:
https://example.com/wp-json/wp/v2/book