Exterior Memory:Permissions Configuration

Revoking Permissions
Every public interactive website (forum, wiki) suffers the same problem: vandalism, usually in the form of spam.

There are two ways to fight this problem:
 * Revoke permissions to make it harder for scripts to make modifications. Unfortunately, this also makes it harder for genuine users to make modifications as well.
 * Monitor changes closely, and revert vandalism.

This page only covers the first item, but adding monitoring is just as crucial to fight spam, perhaps even more crucial if you don't want to annoy your users.

Permissions and Authorization generally involves users to
 * solve a CAPTCHA (small puzzle of recognition of deformed text),
 * sign-up (register an account),
 * confirm an e-mail address,
 * or even manual authorization of the account by the wiki maintainer.
 * restrictions who may edit, create, delete, move article, possible different for each namespace (for example, this wiki restricts viewing permissions in the configuration namespace).

Add a captcha
CAPTCHA is a small test to tell Computers and Humans Apart. Thus, a small puzzle that is very easy for a human to solve, but hard for a computer. Examples of captchas are:
 * Type the text of a distorted image
 * "The number following a three"

Requirement: ConfirmEdit extension.

Configuration: // Captcha to create new accounts require_once("$IP/extensions/ConfirmEdit/ConfirmEdit.php");

That's it. This creates a simple puzzle, e.g. "47 + 2 =" to solve for user before they register. This is currently enough to stop most spammers.

Of course, the fight between spammers and the good guys never ends. It will be a short while before spammers adjust their cracking scripts to solve such an easy problem.

Warning: If you use CAPTCHAs, make sure they are also solvable by people with disabilities. Remember that people with a visibility handicap rely even more on the web then you do, so don't leave them hanging. The

Tip: The very best CAPTCHA is one that you create yourself. A simple challenge like "enter the word 'shoe'" is sufficient. If every wiki has such a very simple question, but it is different for each wiki, then spammer will need to find out the challenge for each individual wiki, and they can not longer deploy scripts. Of course, spammers can still perform a directed attack, but that is easy to solve with good monitoring.

Require users to Sign up
The default user rights for the following permission are true for anonymous access. We should explicitly set this to false (disallow):

$wgGroupPermissions['*']['edit']            = false; $wgGroupPermissions['*']['createpage']      = false; $wgGroupPermissions['*']['createtalk']      = false; $wgGroupPermissions['*']['writeapi']        = false;

Now we should set these back to true for registered users. However, this is optional, as the default permission already do this:

$wgGroupPermissions['user' ]['edit']            = true; $wgGroupPermissions['user' ]['createpage']      = true; $wgGroupPermissions['user' ]['createtalk']      = true; $wgGroupPermissions['user' ]['writeapi']        = true;

Require users to register an e-mail address
This is really by using $wgEmailConfirmToEdit:

$wgEmailConfirmToEdit = true; # only accounts with confirmed e-mail may edit

That's all!

Note: you may see some example code that uses the emailconfirmed group. This is old code; the emailconfirmed group has been removed in MediaWiki 1.13. While it is possible to replicate and extend it's behaviour, I suggest you don't: For one thing, $wgEmailConfirmToEdit also gives a clear error message when a user without confirmed email address tries to edit a page. With the emailconfirmed group, there was only a generic message, leaving the user in the dark.

Only allow page creation after 3 days
autoconfirmed is a hidden group where people are automatically promoted to if they are long-term users.

You can tune the autopromotion using $wgAutoConfirmAge and $wgAutoConfirmCount:

$wgAutoConfirmAge  = 3*3600;  # auto-confirm accounts after 3 days $wgAutoConfirmCount = 0;      # no restriction on number of edits before auto-confirm

For more control, use $wgAutopromote.

The above only controls who belongs to a certain group. To control the permissions of the autoconfirmed group, use

$wgGroupPermissions['*']['edit']                   = false; $wgGroupPermissions['*']['createpage']             = false; $wgGroupPermissions['*']['createtalk']             = false; $wgGroupPermissions['*']['writeapi']               = false; $wgGroupPermissions['user' ]['edit']               = true; $wgGroupPermissions['user' ]['createpage']         = false; $wgGroupPermissions['user' ]['createtalk']         = false; $wgGroupPermissions['user' ]['writeapi']           = false; $wgGroupPermissions['user' ]['move']               = false; $wgGroupPermissions['user' ]['move-subpages']      = false; $wgGroupPermissions['user' ]['read']               = true; $wgGroupPermissions['user' ]['upload']             = false; $wgGroupPermissions['user' ]['reupload']           = false; $wgGroupPermissions['user' ]['reupload-shared']    = false; $wgGroupPermissions['user' ]['minoredit']          = false; $wgGroupPermissions['user' ]['purge']              = false; $wgGroupPermissions['autoconfirmed' ]['edit']      = true; $wgGroupPermissions['autoconfirmed' ]['createpage'] = true; $wgGroupPermissions['autoconfirmed' ]['createtalk'] = true; $wgGroupPermissions['autoconfirmed' ]['writeapi']  = true;

Note that both the user and anonymous (*) permissions are required, as these are true by default.

Manually Authorize Users
It is possible to create a user group, and restrict certain actions to only this group. This requires an administrator to first add a certain user to the group, before the user can make these special actions. This can be done in the special page Special:UserRights.

The configuration is actually very similar to the autoconfirmed configuration above, with the difference that those users are automatically added to the group after some criteria are met.

The following configuration first disallows regular users to move, delete or create pages or upload files. Then it creates a new user group, Editor, for users who are allowed to do these things.

$wgGroupPermissions['user' ]['move']               = false;  # default: true $wgGroupPermissions['user' ]['read']               = true;   # default: true $wgGroupPermissions['user' ]['edit']               = true;   # default: true $wgGroupPermissions['user' ]['upload']             = false;  # default: true $wgGroupPermissions['user' ]['createpage']         = false;  # default: true $wgGroupPermissions['user' ]['createtalk']         = true;   # default: true $wgGroupPermissions['user' ]['move-subpages']      = false;  # default: true $wgGroupPermissions['user' ]['reupload']           = false;  # default: true $wgGroupPermissions['user' ]['reupload-shared']    = false;  # default: true $wgGroupPermissions['user' ]['minoredit']          = false;  # default: true $wgGroupPermissions['user' ]['writeapi']           = false;  # default: true $wgGroupPermissions['user' ]['move-rootuserpages'] = false;  # default: true $wgGroupPermissions['user' ]['purge']              = false;  # default: true $wgGroupPermissions['Editor']['move']              = true; $wgGroupPermissions['Editor']['edit']              = true; $wgGroupPermissions['Editor']['upload']            = true; $wgGroupPermissions['Editor']['createpage']        = true; $wgGroupPermissions['Editor']['createtalk']        = true; $wgGroupPermissions['Editor']['move-subpages']     = true; $wgGroupPermissions['Editor']['reupload']          = true; $wgGroupPermissions['Editor']['reupload-shared']   = true; $wgGroupPermissions['Editor']['minoredit']         = true; $wgGroupPermissions['Editor']['writeapi']          = true; $wgGroupPermissions['Editor']['move-rootuserpages'] = true; $wgGroupPermissions['Editor']['purge']             = true; $wgGroupPermissions['Editor']['delete']            = false; # Only admins may delete pages. $wgGroupPermissions['Editor']['rollback']          = true; $wgGroupPermissions['Editor']['autopatrol']        = true;  # Mark as "approved edit" by default
 * 1) artificially create a new group, editors, who may allow editing all public namespaces

Since this configuration relies on manual adding users to a new group, it is highly recommended that an administrator is notified when a new user registers an account.

Restrict edit permissions per namespace
If you only want to restrict edit, create, delete and move permissions (but always allow viewing), you can use the$wgNamespaceProtection configuration.

The following configuration will first create a new permission, editbyeditor, and a new user group, Editor. Then it makes sure that only the Editor group has this new permission. Finally, we restrict edit access to the namespaces File, Mediawiki, Template, Help, Category and the Custom Namespace Code. This means that regular users can not edit these namespaces, but can only edit the Main, User and all Talk namespaces.

$wgGroupPermissions['Editor']['editbyeditor']        = true;  # custom: allow editing Editor-only namespaces $wgNamespaceProtection[NS_PROJECT]         = array('editbyeditor'); $wgNamespaceProtection[NS_FILE]            = array('editbyeditor'); $wgNamespaceProtection[NS_MEDIAWIKI]       = array('editbyeditor'); $wgNamespaceProtection[NS_TEMPLATE]        = array('editbyeditor'); $wgNamespaceProtection[NS_HELP]            = array('editbyeditor'); $wgNamespaceProtection[NS_CATEGORY]        = array('editbyeditor'); $wgNamespaceProtection[NS_CODE]            = array('editbyeditor');
 * 1) no need to set ['user']['editbyeditor'] to false, as the default permission is already false.
 * 1) Namespaces that can only be edited by Editors, not by regular users.
 * 2) restrict the namespaces to only Main, Talk, User, User Talk, and all other Talk page, but not these.

Warning: Do not forget to list your additional namespaces, if you want to restrict access to them as well.

Restrict view permissions per namespace
If you also want to restrict view permission beside the edit permissions, you need to use Lockdown extension.

The following configuration creates a new user group, Friends, and restricts any access to the newly created Config namespace to only members of this group. In this case, Friends always have read permissions to the Config namespace. This configuration does not give Friends any edit or create rights, but since (in my configuration elsewhere) any registered user can still edit, and anyone in the Editor group can create pages, this means that those combined right apply to the Config namespace as well.

Remember that the Lockdown extension can only be used to restrict access, not to grant it. If access is denied by some built-in setting of MediaWiki, it cannot be allowed using the Lockdown extension.

// Restrict certain namespaces from editing and viewing require_once("$IP/extensions/Lockdown/Lockdown.php"); $wgGroupPermissions['Friend']['read']              = true; $wgNamespacePermissionLockdown[NS_CONFIG]['*']      = array('Friend'); $wgNamespacePermissionLockdown[NS_CONFIG_TALK]['*'] = array('Friend');
 * 1) artificially create a new group, friends, who may view private namespaces.
 * 1) restrict viewing and editing for the Config namespace to the Friend group only.

Security Issues
Warning: MediaWiki was not designed to restrict viewing. In fact, WikiMedia's Security issues page lists as much as 16 methods for people to view pages even after you restrict viewing (by using caching, RSS Feeds, inclusion, etc.).

Most of these methods have been taken care of, but you need to keep the following three things in mind.


 * 1) Make sure you use MediaWiki 1.12 or higher (you should anyway, 1.12 is getting old)
 * 2) Be aware that it is not possible to restrict image viewing. If an attackers knows the name of an image, he there is nothing MediaWiki can do to stop him viewing it. If you want to stop this, don't use a wiki.
 * 3) The template namespace was designed to include page snippets into other pages. This can be abused to view pages in restricted namespaces. You should disable this by using the $wgNonincludableNamespaces parameter:

$wgNonincludableNamespaces = array(NS_CONFIG, NS_CONFIG_TALK);