Tag Archives: wordpress mu

WordPress MU and user registration grief

WordPress MU (WPMU) is a great tool.

It’s basically a fork from the main WordPress software that lets you set up and maintain potentially vast numbers of blogs from a single codebase. It’s particularly popular with universities and HE institutions, such as Harvard Law School (http://blogs.law.harvard.edu), and a range of UK universities including here at Kent.

Why registration?

So, why would you want to allow user registration for blogs? Mostly, blogging is all about free commenting on posts, and the onus is on the blogger to filter out dodgy comments.

If you’re like me with just a handful of comments every month, fine.

If you’re an institution like a university, this opens up the proverbial can of worms (I’ve never seen a real can of worms, but I’m sure it’s not pretty) to do with complaints, disciplinary procedures, legal stuff. Far better to force people to register before making a comment, so there’s at least a way of telling whether they’re from the institution, or a member of the public.

No comment.

WordPress MU registration system is bad. Not in a cool sense of bad. It’s just terrible.

1. Confusing to users. You might want to register for MyHappyBlog because you want to comment on a blog post. The moment you register you’re sent on a multi-click process which takes you far, far away not just from the familiarity of MyHappyBlog, but from the post, and any memory of the stinging critique you were going to deliver. No comment, quite literally.

1a. …oh and by the way, just to make it even more confusing, the user will be sent an impossible-to-remember password after they’ve registered. Although this is touted as being secure (I’m sure it is), it’s just impractical. Either the user will forget the password, or they’ll forget to change it.

2. Confusing to developers. WordPress MU registration works fine so long as you follow the way it does things. If for some bizarre reason you want to change the way the registration page looks (you mad fool!), you have to change the core code. As any developer will tell you, this is generally a very stupid thing to do, and ipso facto a stupid thing to force people to do.

Logged out

I should just add that it’s actually not just the registration system in WPMU. Standard WordPress has a curious login page which is very hard to change. Yes, you can get round this in part with filters and plugins and whatnot. But the point is that changing the way something looks should never, never, require a developer to hack around a bit. This is what themes are for.

Summary

My advice to anyone considering user registrations in WPMU? Don’t. The fact that the registration system is so quirky might be indicative of the relatively relaxed approach most bloggers have towards commenting. You may want to ask why it is that you absolutely must have user registrations for your institutional blogs.

wordpress mu XSRF

Cross-site request forgery (XSRF). It’s something that’s becoming a big issue in internet security, and yet is still relatively poorly understood by many developers. If you don’t already know what it is, you can find an excellent introduction in wikipedia:

http://en.wikipedia.org/wiki/XSRF

In a nutshell, anything on your website is a security risk if it lets someone modify something on your system (eg an entry in a database) without first making sure that the request for that modification actually came from your site. This isn’t restricted to a URL query string. Forms are probably the worst offender because many developers seem to think they’re somehow safe. They’re not.

A good way of preventing a XSRF attack is to give each form a unique identifier which keeps changing. Only your web application will know for sure that a request has come from a form on your site, because that application generated the identifier in the first place and can cross-check it against an entry in a database. Drupal does this, and so does WordPress (including WordPress MU).

Here I’m focusing on how WordPress MU does the XSRF protection. It’s called, wait for it…

Nonce?

ok, ok. Get the sniggering done now. And relax…

To the good people at WordPress (and seemingly everyone in America) nonce has only one – very unfunny – meaning: a word or expression which only ever occurs once. ie. a unique key which changes its value every time it’s used.

By default all WordPress forms use nonce values to help prevent XSRF. If you write your own plugins, to get this to work in WordPress is amazingly simple. Just put this in your home-grown form:

 wp_nonce_field('my_nonce_phrase');

where ‘my_nonce_phrase’ can be any unique phrase which acts as a base for the system-generated nonce key. It’s usually a good idea to use something like plugin-name+form-name so you eliminate the risk of clashing one nonce value with one from a different form. But basically you can use any phrase you like.

If you need more info, the WordPress API listing is here:

http://codex.wordpress.org/Function_Reference/wp_nonce_field

If you want to put a nonce in a URL rather than a form, just use the very similar:

wp_nonce_url('theurl', 'my_nonce_phrase');

where this time ‘theurl’ is, predictably, the url that you want to noncify, and ‘my_nonce_phrase’ is once again your unique phrase which is going to act as the seed for the eventual nonce key.

Whitelist

There is however a slight catch. Some forms on the backend are forms where you want someone to update various options parameters. For example, if you’ve built a plugin and want someone to be able to set various plugin default options. In standard WordPress, you use options.php as the form’s action, and can use the following as a nonce field:

wp_nonce_field('update-options');

This way, when the update button is pressed the fields you’ve added to your form will automatically get updated as part of the options.php code, and the nonce system will be happy that the form came from the right website. Everyone’s smiling. Everyone’s happy.

This doesn’t work with WordPress MU, however.

Instead you need to add this to your form:

wp_nonce_field('my_nonce_phrase-options');

where adding -options to the end is crucial if you want options.php to work properly. I’m not sure why. It just is.

Finally, in your plugin you need to be able to alter the nonce whitelist ie. the list of option names which are accepted by options.php. You could just alter options.php, but that would be crazy. Instead use a filter to intercept the whitelist and add your own values to it:

function my_plugin_alter_whitelist_options($whitelist) {
  if(is_array($whitelist)) {
    $option_array = array('my_nonce_phrase'=>array('plugin_option_1', 'plugin_option_2', 'plugin_option_3', 'plugin_option_4'));
    $whitelist = array_merge($whitelist, $option_array);
  }
  return $whitelist;
}
add_filter('whitelist_options', 'my_plugin_alter_whitelist_options');

Yes, it’s ugly and bad. But there doesn’t seem to be any way round this for WordPress MU and forms used for setting your own options in a plugin.

Summary

WordPress MU lets you build forms which are relatively safe against XSRF attacks. Doing this is easy, and takes just one line of code in your form. A word of warning: adding protection to forms which make use of WordPress’s options feature is more fiddly in MU than it needs to be, but still not too bad.

WordPress MU 2.7 released

Finally, after much holding of breath and anticipation, WordPress 2.7 and its swanky interface comes to MU-world. Yay!

wordpress mu logo

As is typical with the quasi-underground nature of WordPress MU, version 2.7 wasn’t so much announced as… became apparent. ie. if you happened to download it you’d find the version number was different. A WordPress MU forum thread showed the general confusion about whether 2.7 was still in beta, or an actual stable release:

http://mu.wordpress.org/forums/topic.php?id=10952

Anyway at first sight everything seems to be working fine after an update from WordPress MU 2.6. Plugins, even home-grown ones are doing their thing. I guess one of the main advantages of using a fork which is typically a couple of months behind the vanilla-Wordpress is that any regularly-updated plugins and themes you may already be using will generally ‘just work’ with a new version of WordPress MU.

wordpress mu and akismet: wordpress_API_key problems

A big problem for any blogger is spam comments, and the Akismet plugin for WordPress is basically an essential item. It does its job really well, and on this blog I’m only aware of the occasional bit of spam. Hoorah for Akismet!

But things aren’t quite so smooth if you need to do strange, weird things with your blog. Like set up lots of blogs off one codebase. Sound crazy? Well multiple blogs is actually something lots of organizations and universities need, and the WordPress fork - WordPress MU –  fits the bill brilliantly. In a few seconds you can create a new blog for someone in your organization, and off they go.

Oops

Hold on. Not quite, you need to enter that long impossible to remember API key each time you make a new blog. It’s not hard to copy and paste from the word doc you’ve got saved somewhere on your… oh now where was it again? No, far better would be for WordPress MU to automagically set Akismet up for you each time you make a new blog.

That must be easy? Right? Erm… no, not really.

Deep breath… and on with the technical stuff

The latest version of Akismet at time of writing doesn’t work in the way described at the top of the akismet.php file. Supposedly if you hard-code your API key into $wpcom_api_key this will fix everything. This simply doesn’t work, thanks to a coding oversight in akismet_stats_display(). In that function, $wpcom_api_key is mentioned as a global variable, but isn’t actually used anywhere in the function. So much for that piece of magic. Maybe in a future version?

The second problem is that even if you have your wordpress API key entered in your database, it won’t have any effect until the key has been registered with Akismet, behind the scenes. I couldn’t find any documentation on this anywhere, but akismet_verify_key() seems to be where this process is actually going on.

Not finished yet. You can’t just make your own plugin to call akismet_verify_key() each time a new blog is created. Sadly akismet_verify_key() contains a call to get_option(‘home’) for the much-needed blog url. Because you’re in the process of making a new blog from an existing blog’s admin area, get_option(‘home’) returns the url of the existing blog, not the new one that you’re interested in.

Sigh.

My solution

Build your own verify_key function, as follows:


function verify_key() {
  global $akismet_api_host, $akismet_api_port, $current_site;
  $key = 'myapikey';
  $blog = urlencode('http://' . $current_site->domain . '/' . stripslashes(htmlentities($_POST['blog']['domain'])));
  $response = akismet_http_post("key=$key&blog=$blog", 'rest.akismet.com', '/1.1/verify-key', $akismet_api_port);
}

Stick this in a plugin of your own making. Note that the awkward way of setting $blog is needed because we have no other way of retrieving the URL of the blog we’re in the process of making, rather than the one we’re currently at while making the new blog… if you see what I mean. In fact, in the newly-released WordPress MU 2.7 you can use this line instead:

$blog = urlencode('http://'.DOMAIN_CURRENT_SITE.PATH_CURRENT_SITE.stripslashes(htmlentities($_POST['blog']['domain'])));

Not much difference, but maybe a tad neater. The choice is yours. 

Now add in:

add_action('wpmu_new_blog', 'verify_key');

to make sure the function gets called every time a new blog is made.

And there you go! A lovely hacked solution to a problem which could be resolved with a bit of tweaking to the Akismet plugin. To be fair, WordPress MU is a fairly new thing, and I guess the guys who wrote the Akismet plugin haven’t had a chance to really test is fully with WordPress MU.