On my site i have one form for client to submit their WordPress site details. On that form containing these fields WordPress admin url, username, and password. I want to check their login details are valid before submitting the form. How i do that?
If there any way to do by using WordPress REST API?
If anyone know please help me Thanks !
On my site i have one form for client to submit their WordPress site details. On that form containing these fields WordPress admin url, username, and password. I want to check their login details are valid before submitting the form. How i do that?
If there any way to do by using WordPress REST API?
If anyone know please help me Thanks !
Share Improve this question edited Apr 23, 2018 at 9:25 bueltge 17.1k7 gold badges62 silver badges97 bronze badges asked Apr 17, 2018 at 12:06 developermedeveloperme 1415 silver badges18 bronze badges 7 | Show 2 more comments3 Answers
Reset to default 3 +25Getting user names and passwords is a horrible idea I hope no user will actually agree to, but beyond that your idea to do it from JS is going to fail due to CORS, which means you will have to do it in AJAX to your server, and let your server try to login, which in turn will most likely flag it as a brute force attacker in no time, and all the major security players will just automatically block the requests.
You need to redesign you software to not need user name and password, probably use something like oauth2 instead. If oauth2 is not applicable for your situation.... well, tough luck.
First off: there are many reasons why the following code could fail. There is no way to have a system that works everywhere. This is due to various security plugins introducing many different concepts.
Having said that, this code worked for a plain installation as well as one with Wordfence (with not super strict settings) enabled.
wp_remote_post()
is the key function in this function. It allows you to send POST requests to remote hosts - which is exactly what you want if you want to check a login.
function WPSE_test_remote_login($url, $username, $password) {
// remove trailing slash if it exists
$base = rtrim($url, '/');
// login url
$url = $base . '/wp-login.php';
$args = [
// the inputs that get POSTed
'body' => [
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Submit',
'redirect_to' => $base . '/wp-admin/',
'testcookie' => 1,
],
];
// make the actual request
$response = wp_remote_post($url, $args);
// only one cookie? then failed login
if ( ! is_array($response['headers']['set-cookie'])) {
return false;
}
// if a cookie that contains wordpress_logged_in is set
// the login was successful
foreach ($response['headers']['set-cookie'] as $cookie) {
if (stripos($cookie, 'wordpress_logged_in') !== FALSE) {
return true;
}
}
return false;
}
I tried this in my local environment, you can get the necessary fields that are usually sent if you access the wp-login.php in your browser.
Then I checked the $result
and compared the difference between correct and wrong password. For a failed login, $response['headers']['set-cookie']
looked like this
string(45) "wordpress_test_cookie=WP+Cookie+check; path=/"
or this
array(3) { [0]=> string(128) "__cfduid=df131...; expires=Sun, 21-Apr-19 12:35:00 GMT; path=/; domain=.example; HttpOnly" [1]=> string(100) "wfvt_144...=5ad...; expires=Sat, 21-Apr-2018 13:05:00 GMT; Max-Age=1800; path=/; HttpOnly" [2]=> string(74) "wordpress_test_cookie=WP+Cookie+check; path=/; domain=.example; secure" }
However, a successful login returned these cookies
array(4) { [0]=> string(45) "wordpress_test_cookie=WP+Cookie+check; path=/" [1]=> string(209) "wordpress_852...=test%7C15...; path=/wp-content/plugins; HttpOnly" [2]=> string(199) "wordpress_852...=test%7C15...; path=/wp-admin; HttpOnly" [3]=> string(201) "wordpress_logged_in_852...=test%7C15...; path=/; HttpOnly" }
We see that wordpress_test_cookie
will always get set. However, wordpress_logged_in_852...
was only set for successful logins. So we can determine that if this exists, the credentials are correct.
There is no way to achieve this without any custom API routes. But of course, you can register such route (or use AJAX instead), if you can edit theme or install plugins on that site.
So, let's do this with REST API...
function my_register_api_hooks() {
register_rest_route(
'my_namespace', '/check-login/',
array(
'methods' => 'POST',
'callback' => 'my_api_check_login_callback',
)
);
}
add_action( 'rest_api_init', 'my_register_api_hooks' );
function my_api_check_login_callback($request){
$user = wp_authenticate_username_password(null, $request['username'], $request['password']);
if ( is_wp_error($user) ) {
return array('error' => $user, 'user' => false);
}
return array('error' => false, 'user' => $user->ID);
}
When you'll send a POST request to
http://example/wp-json/my_namespace/check-login/
containing username
and password
, you'll get JSON like this:
{
"error": false,
"user": 1
}
where 1
is the ID of user found for given credentials, or
{
"error": "...", <- this will contain error messages
"user": false
}
You have to be aware that this code only checks if user credentials are correct. It will not log user in.
And what if you have no control over site you want to check?
Then there is no way to register your own routes and there's no way to use REST to check user credentials. But... You can use XMLRPC...
One way will be using this library: WordPress XML-RPC PHP Client. It will do the job for you almost all the way or you can use native WP_HTTP_IXR_Client class.
You can use wp.getUsersBlogs
method for checking if given credentials are correct.
wp-login.php
. – mmm Commented Apr 17, 2018 at 12:44