6

I'm writing a plugin that creates an API endpoint that validates username/password pairs.

I'm currently using wp_signon() to check whether the username/password combo works. This works fine when the credentials fail because it returns an error object. But when the credentials are good, it automatcially signs in that user, so my endpoint returns a whole page.

The codex currently doesn't even mention the fact that it automatically logs in the user. It also doesn't appear to accept a parameter to suppress that functionality. For my purposes I simple boolean would be fine.

UPDATE: I had to choose one single answer, but there was a lot of useful info several of the other answers which I'll try to summarize briefly here...

  1. There IS a function that does exactly what I was trying to do: wp_authenticate($username, $password) HOWEVER, it comes with one drawback. It will automatically set the login cookies which can create problems in a situation like mine. So be careful. This function is not currently in the codex.

  2. The best choice for what I'm doing is wp_authenticate_username_password($user, $username, $password) because it DOESN'T set the login cookies. This function is more documented, but the REALLY important detail that wasn't in the codex is that you can pass NULL as the first parameter. This means you can effectively use it to do exactly like wp_authenticate() without worrying about the cookies getting screwed up. Read the documentation so you don't get confused by the response. It returns a either a WP_User object or a WP_Error (not a boolean!).

4
  • The Codex is user driven. Just log in and change/edit/add what you think is missing. (Look at it, like you look at Wikipedia).
    – kaiser
    Commented Aug 9, 2012 at 16:55
  • Note: wp_authenticate doesn't actually set the login cookies, that happens in wp_signon. However, wp_authenticate will apply all hooked authentication methods, so if a valid auth-cookie is sent along with the request, then it can validate the user regardless of the username/password. If you just want to check the username password, wp_authenticate_username_password is indeed correct.
    – Otto
    Commented Aug 13, 2012 at 21:52
  • did you ever release this plugin/endpoint?
    – lofidevops
    Commented Oct 24, 2017 at 22:02
  • @d3vid This was for a private project from years ago, so the code would need to be updated to be compatible with current WP. But if this is something you're interested in email me. Commented Oct 24, 2017 at 22:35

4 Answers 4

10

There is a function in the user.php of the core files called wp_authenticate_username_password that seems like what you're looking for.

If you want to avoid throwing in the $user object (you probably only have the username + password), then just throw null as 1st function argument in:

$check = wp_authenticate_username_password( NULL, 'some_username', '#thepassw0rd' );

You can then simply check the result with is_wp_error( $check ).

4
  • This doesn't do what it sounds like. It's a common mistake (which I've made). However, I just discovered a function which actually does what we want! See me answer... Commented Aug 9, 2012 at 16:54
  • 1
    +1 seems to be the perfect way. I hope you don't mind the edit.
    – kaiser
    Commented Aug 9, 2012 at 16:54
  • @kaiser "Huh". I never realized you could pass NULL as the first parameter. That's good to know. Also check out wp_authenticate() (see my answer). I just found it after weeks of searches. Commented Aug 9, 2012 at 17:03
  • Definitely most efficient way.
    – Adam
    Commented Aug 9, 2012 at 17:04
2

Use,

and

Explanation

// get user by login via the supplied username (form input)
$user = get_user_by('login', $username);

//assign user ID based on user login name
$user_id = $user->ID;

// get user data by passing the assigned $user_id variable to get_userdata
// which returns the user object and a host of user related info to access
$user_data = get_userdata($user_id);


// assign the username and password to variables
$user_login = $user_data->user_login;
$user_pass = $user_data->user_pass;

// check the username/password against the submitted input values
if ($user_login = $username && $user_pass = $password) {

// do something...

Notes

  • $username should validate true by default otherwise a user object would not have been returned if the $username supplied did not match one already existing in the database. Therefore the validation then hinges on the $password variable which stores the form input supplied by the user.

  • There might be a more efficient way for you to achieve this, either by shortening the existing code or by using other API functions.

UPDATE

Based upon the suggestion by fdsa you could in turn use wp_authenticate_username_password in this fashion,

$auth = wp_authenticate_username_password($user, $username, $password);

if (!$auth->user_login = $username && !$auth->user_pass = $password) {

echo 'not authenticated';

} else {

echo 'authenticated';

}

But even better than that,

$auth = wp_authenticate_username_password($user, $username, $password);

if (is_wp_error($auth)) {

echo 'not authenticated';

} else {

echo 'authenticated';

}

Really the credit/marked answer ought to be given to fdsa for the most efficient method by way of (sadly) undocumented WP core function.

http://wpseek.com/wp_authenticate_username_password/

1
  • This is great. But get_userdata will return the hashed password (not the plaintext). Any advice how to sidestep this? Commented Aug 9, 2012 at 16:33
2

Disclaimer: This answer should just show what's going on behind the scenes and is not meant to be a real life example on how to do things.


Backtrace

wp_signon() calls wp_set_auth_cookie(), which then calls wp_generate_auth_cookie(). The result will be used inside setcookie() as 2nd argument.

(Non-performant) fun with filters

a.k.a. tricking WordPress the wrong way.

You could then just jump into the 'auth_cookie'-filter inside wp_generate_auth_cookie() and simply set it to null or something else than the SECURE_AUTH_COOKIE or AUTH_COOKIE value. This will then leave you with a senseless cookie, that can't log in.

0

"Ta-da": wp_authenticate($username, $password)

It's not in the codex at all, but you can look it up on wpseek.

It does exactly what it sounds like. Takes a username and plain text password and returns either a WP_User object or a WP_Error... and it DOESN'T log anyone in.

One note of caution! The following will ALWAYS return true (because the function returns an object either way):

$auth = ( wp_authenticate($username, $password) ) ? TRUE : FALSE;

You'll probably want to do something like this:

$test_creds = wp_authenticate($username, $pass) ;
$class = get_class($test_creds);
$auth = ( $class == 'WP_User' ) ? TRUE : FALSE ;

I hope this helps someone.

6
  • You can use instanceof or is_a() to check for WP_User. You could also simply use one of the above functions and remove the filter on authenticate...
    – kaiser
    Commented Aug 9, 2012 at 17:03
  • 2
    Recommend using is_wp_error($auth) which will return TRUE if fails authentication and FALSE if passes authentication.
    – Adam
    Commented Aug 9, 2012 at 17:07
  • 2
    One more note: This will not log you in, but it will still leave you with the cookie set, as the function calls the `'authenticate filter. If you go with that solution, you should make sure, that all filter callbacks are removed. Else the sky could fall on your head :)
    – kaiser
    Commented Aug 9, 2012 at 17:20
  • That's good to know about. Does wp_authenticate_username_password( NULL, 'some_username', '#thepassw0rd' ); have the same problem? Can you elaborate slightly on the sky falling? What will go wrong? Commented Aug 9, 2012 at 17:56
  • 3
    Note: Instead of using wp_authenticate you want to actually use user_pass_ok($user_login, $user_pass) which in turn uses wp_authenticate as its the proper wrapper function which returns true/false. However as @kaiser said, cookie is set via authenticate filter. The latter wp_authenticate_username_password does not appear to set cookie.
    – Adam
    Commented Aug 9, 2012 at 18:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.