The wp-login.php page calls the wp_signon() function. That function in turn calls wp_authenticate() which is where the ‘authenticate’ filter is invoked.
While this involves the wp-login.php page, I would think as long as wp_signon() is called somewhere and the returned value is handled properly, there is no need for the actual login page. What may be more difficult to do is preventing WP from loading the login page when it needs new authorization or when the user logs out.
I guess the problem I’m having is that everything seems highly password-centric.
In my case I want to log users in based on a redirect from another site. The redirect URL query string will include a user login name and a Message Authentication Code, but no user password. My plugin will need to validate the Message Authentication Code, and log the user in if the validation succeeds. At no point will it have access to a user password however.
I guess this must be possible since there are a number of existing plugins that claim to provide SSO functionality. But I’m not sure how to achieve it since all the relevant functions (including wp_signon and wp_authenticate) seem to require a user password.
I’ve not done this, but I think it will work. It does center on the ‘authenticate’ filter. You need to remove the default ‘authenticate’ filter callback. It is wp_authenticate_username_password() and was added with a priority of 20 to take 3 parameters at line 71 of wp-includes/user.php. Then add in your own callback to ‘authenticate’. Your callback should return the correct WP_User object on success and a WP_Error object on failure.
Now you can call wp_signon(), perhaps supplying the message authentication code for the password. Since you authentication callback knows the ‘password’ is actually the message authentication code and validates it accordingly, it all should work out.
bcworkz, thanks for the response.
I’m wondering whether it would be best for me to create my own page to handle the credentials, or to try to send everything through wp-login.php.
If I send everything through wp-login.php I it looks like I’d have to shoehorn everything into the standard log and pwd parameters.
On the other hand, if I was to create my own page, I’m not sure what’s the minimum I’d need to require in order to use wp_signon, i.e. is it sufficient to require('../../wp-includes/user.php')? Moreover, what’s the best way to do that without making assumptions about where the plugins directory lives (since I understand it can be moved)?
It’s hard to know how much WP to load for any given function. I’m always inclined to require once wp-load.php and load the whole thing rather than risk missing something. As you noted, relative references would be bad. It’s better to use one of the site URL template tags to point to the right directory. If you plan on putting your plugin in the repository, you shouldn’t require wp-load.php or anything. There’s a few ways around requiring wp-load.php, such as AJAX calls.
Here’s a thought. Besides changing the ‘authenticate’ filter to your own process, why not send your page’s login data to wp-login.php instead of your custom page that needs to require wp-load.php? As long as you send all the correct fields in your POST, you can send any other fields you want, the wp-login page will not care. It will process the request as normal and call wp_signon(). Your ‘authenticate’ filter callback can grab the extra data directly from $_POST and act accordingly.
It’s better to use one of the site URL template tags to point to the right directory.
Do you mean something like this?
<?php echo site_url(); ?>
If so I’m not sure I see how that would work—wouldn’t that in itself necessitate at least require('wp-includes/link-template.php');? In which case it seems like a catch-22.
If you plan on putting your plugin in the repository, you shouldn’t require wp-load.php or anything.
Do you have a citation for this? I couldn’t find anything in the guidelines.
Besides changing the ‘authenticate’ filter to your own process, why not send your page’s login data to wp-login.php instead of your custom page that needs to require wp-load.php?
Thanks for the suggestion, I will try this approach.
Re: Site URL tags. Well, you wouldn’t echo it out, rather use the return value to build a require path that is not relative to your plugin folder location. This would only be applicable if you chose to require wp-load.php or whatever. You at least deal with relative reference objection to this technique. It wouldn’t fix the general objection to it. My comment was intended for situations where the plugin is for your own sites and not public distribution.
Re: Repository. No, I’ve never seen an explicit statement. I do know several author’s whose plugins were rejected because of this. Aside from the relative reference issue, I’m not sure what reasoning for the restriction is, several WP core pages do exactly this.
Good luck on your project, if you have any more questions, just ask.