Page-by-page authentication in MediaWiki
In the interests of centralizing information, we’ve started an internal wiki at the Center that will eventually function as a sort of dynamic handbook to our facilities, staff and projects. The choice of a wiki was ideal, because each staff member can flesh out the documentation on his or her projects, and since it’s for internal use, we can take the general good intentions of users for granted.
However, there are some pages that will need to be restricted to certain users (things like payroll/budget information, or staffing discussions), so I went ahead and wrote a small plugin that allows any user to restrict access to a wiki page by embedding the allowed usernames within a special tag (working off of a really useful blog post outlining MediaWiki plugins).
Here’s what you do. Save the following code into a file called “accessControl.php” in your MediaWiki /extensions directory
< ?php
// MediaWiki extension that enables access restriction on a page-by-page
// basis
// Added 5/3/05 by Josh Greenberg
// [based on code snagged from http://daryl.learnhouston.com/?p=125]//Add the hook function call to an array defined earlier in the wiki
//code execution.
$wgExtensionFunctions[] = “wfAccessControl”;//This is the hook function. It adds the tag to the wiki parser and
//tells it what callback function to use.
function wfAccessControl() { global $wgParser; # register the extension with the WikiText parser $wgParser->setHook( “accesscontrol”, “controlUserAccess” );
}// The callback function for user access
// Create array of users with permission to access this page $usersAccess = explode(”,,”, $input); // Trim leading whitespaces from usernames foreach ($usersAccess as $userEntry) { $userEntry = strtolower(ltrim($userEntry)); } // Put up an error message if current user doesn’t match // accesscontrol list if (!in_array(strtolower($wgUser->getName()), $usersAccess)) { echo ‘‘; exit(); } return $output; } ?>
function controlUserAccess( $input ) { // Grab currently logged in user global $wgUser;
Then, add a line to the bottom of your LocalSettings.php to tell it to include the plugin:
include("extensions/accessControl.php");
That’s it for the installation. To restrict access on a page-by-page basis to specific users, just include the names of the allowed users within an
<accesscontrol>Fred,,janedoe,,Josh Greenberg</accesscontrol>
Be careful with this! If you’re restricting access to a page, make absolutely sure that you’re including your own username within the <accesscontrol></accesscontrol> tags, or else you won’t be allowed to reload the page to fix your mistake. If you find yourself locked out of a page that you need access to, you’ll have to disable the plugin.
October 28th, 2005 at 3:22 am
This seems to be what I am looking for for my wiki but I cannot get it working on MediaWiki 1.5. Has it been tested on that version?
Thank you.
November 18th, 2005 at 3:03 pm
Hasn’t yet, though we’re in the process of upgrading our internal wikis to 1.5, so I’ll report back once I’ve got a good sense of how this might need to be modified.
December 4th, 2005 at 5:45 pm
Just a note to say that I’m really looking forward to this too. Thanks for your work!
December 12th, 2005 at 10:31 am
I have tested it on 1.5. Working perfectly. Needs 2 PHP fixes:
for ($i=0; $i’;
instead of
echo ‘’;
December 12th, 2005 at 10:33 am
Working perfectly on 1.5. Needs PHP fixes:
for ($i=0; $i<count($usersAccess); $i++) {
$usersAccess[$i] = strtolower(ltrim($usersAccess[$i]));
}
and
echo ‘<body onLoad=“javascript: alert(‘Not Allowed’)”>’;
December 12th, 2005 at 10:35 am
Working perfectly on 1.5. Needs PHP fixes:
for ($i=0; $i
$usersAccess[$i] = strtolower(ltrim($usersAccess[$i]));
}
and
echo ‘<body onLoad=“javascript: alert(‘Not Allowed’)”><body>’;
December 17th, 2005 at 1:58 am
Dmocho, I don’t know if I’m just being dense of what, but I really don’t understand what you’re saying — what exactly are the “fixes”? I would really like to get this working with 1.5, but I can’t find any of the above characters so I don’t know how I’m supposed to replace what with what…
December 19th, 2005 at 6:37 pm
Youre not doing lowercase() on both sides of the comparison. Is that right?
in_array(strtolower($wgUser->getName()), $usersAccess)
If I enter the username properly, it won’t match unless the username itself is lowercase.
Why double comma?
Anyway, it should be noted that this method has the same insecurity problem as does TWiki’s per-page access control. There is a “search hole” in the security. In other words, searching for a word on a restricted page will return a snippet of the page. Subsequent usage of search can potentially retrieve the content of the page regardless of this access control.
December 19th, 2005 at 6:37 pm
Also, users with access ‘sysop’ should arguably always have access to such pages.
December 19th, 2005 at 7:10 pm
Hmm. Basically, an extension-based page access control method will only work when the page source is being rendered for display.
Any way you can think of to see a page’s source will circumvent this access control. Search is not the only way. It is possible to see the entire content of the page knowing only the page name and using only standard MW features. This should not be relied upon for true security.
December 25th, 2005 at 11:52 am
Hi everybody,
For some weird reason, the tag is not always interpreted, so acces control does not work at all. It sounds like cache side effects, though cache is not enabled on my wiki instance…
Any clue?
December 27th, 2005 at 2:11 am
Howdy…so, I’m happy that people are finding this code worthwhile to even bother trying out, but I’ll have to stay out of the discussion for another two weeks (I’m in New Zealand on my honeymoon, hence the absence)…more when I’m back in early January. Until then, I’ve turned comments to “unmoderated” (lord help me), so discuss away…
January 23rd, 2006 at 9:00 am
Greetings from Germany (Just to give you an idea where your extension is needed around the globe
It would be great to build the ACLs depending on groups (also including SYSOP status).
If you are too exhausted from your honeymoon (by the way: congrats) You might use the user and user_groups table to require the match for a userI D there and in the user table:
SELECT count (*) FROM user_groups A1, user A2 WHERE A2.user_id = A1.ug_user AND A2.user_name like ‘marquee’
AND A1.ug_group=‘sysop’;
You can change the “sysop” group by any other group name (gathered from you authorization Tag content. However, I believe they will change the table structure there, since the user_groups table contains the group name instead of an counter/unique Tag. But you can then simply manage the ACLs on group base without implementing somethin on the http side.
@Keith T.: This might be implemented not only in the display, but also in the Edit, search RSS Feed etc. to implement it secure.
January 28th, 2006 at 12:10 am
Could this be modified so that all the pages would still be viewable by everyone but access control could restrict who gets to edit the pages?
February 16th, 2006 at 5:51 pm
Thank You! Just the extension I was looking for to allow the users to secure some pages without requiring admin rights or config changes.
It does the job of blocking read access, but the changes go out on the RSS feed, you can get to Edit via the history page or hacking the url and see the full content in edit mode.
It would be nice to block the RSS feed but I’d really like to block the edit page.
I had a look through trying to spot places to plug in an additional check includes/EditPage.php function edit() seems to be the place to check but I’ve no idea how to check the tag from here. Any ideas?
PS. Hope you enjoyed your holiday. I’m a native of Auckland, New Zealand.
February 17th, 2006 at 8:25 pm
Does anyone know of an extension that does the opposite? I need to block people off from everything besides just a few pages. Basically, I have a corporate website that I want to limit people’s access to so that people from one department can’t view anything beyond their own department. Any ideas? Thanks in advance.
February 19th, 2006 at 7:03 pm
Michael there are some extensions that allow creation of user groups, adding users to those groups and then restricting access rights based on those groups. You could probably combine this with customer Namespaces so that each group may only access their own Namespace.
But I recommend a simpler solution – multiple Wikis. Setup one wiki, configure it for logged in users only, create the basic structure and global users you want for all departments, then create a copy per department.
February 21st, 2006 at 11:24 pm
I’ve thought about the seperate wikis, but I like the idea of my group (the one with all the control) not having to check multiple sources to remain up-to-date. I’ll look into those user group extensions and also look into setting up multiple wikis. We’re also looking into the possibility of going with multiple wikis that’ll sync to allow for a centralized repository. I’ll let you guys know what works out the best.
February 27th, 2006 at 2:28 pm
Could anyone get it to work, I just went through the installation on mediawiki 1.5.x and it didn’t even parse the tags. I really want this thing to work on my machine.
I’m not sure what you meant by
Working perfectly on 1.5. Needs PHP fixes:
for ($i=0; $i
$usersAccess[$i] = strtolower(ltrim($usersAccess[$i]));
}
and
echo ‘’;
what should i change to what? and put echo after/before what?
March 5th, 2006 at 12:45 pm
05/03/2006
//make accescontrol valid for users an groups
//u:juampe,g:graph,u:ruben
//Is compatible with restrict patch
//Make ACL bypass to restrict an viewrestrict groups
//TODO: make a nice deny page
$wgExtensionFunctions[] = “wfAccessControl”;
//This is the hook function. It adds the tag to the wiki parser and
//tells it what callback function to use.
function wfAccessControl() {
global $wgParser;
# register the extension with the WikiText parser
$wgParser->setHook( “accesscontrol”, “controlAccess” );
}
// The callback function for user access
function controlAccess( $input ) {
// Grab currently logged in user
global $wgUser;
//restrict viewrestrict group can bypass
if(in_array(‘viewrestrict’,$wgUser->mGroups)||in_array(‘restrict’,$wgUser->mGroups)){
return;
}
//get users
preg_match_all(’/u:(\w+),?/’,$input,$usersAccess);
preg_match_all(’/g:(\w+),?/’,$input,$groupsAccess);
//If not restriction is set, then exit and grant
if (((!is_array($usersAccess1)) && (!is_array($groupssAccess1))) ||
((count($usersAccess1) == 0) && (count($usersAccess1)))) {
return;
}
$cleanedUsersAccess[] = “”;
// Trim leading whitespaces from usernames
foreach ($usersAccess1 as $userEntry) {
$userEntry = strtolower(ltrim($userEntry));
array_push($cleanedUsersAccess, $userEntry);
}
$cleanedGroupsAccess[] = “”;
// Trim leading whitespaces from usernames
foreach ($groupsAccess1 as $groupEntry) {
$groupEntry = strtolower(ltrim($groupEntry));
array_push($cleanedGroupsAccess, $groupEntry);
}
// Check Group access
foreach($cleanedGroupsAccess as $groupEntry) {
if(in_array($groupEntry,$wgUser->mGroups)){
return;
}
}
// Put up an error message if current user doesn’t match
// accesscontrol list
if (in_array(strtolower($wgUser->getName()), $cleanedUsersAccess)) {
return;
}
//Access Denied
print “User: “.$wgUser->getName().” Access Denied”;
print “Group: “;
foreach($wgUser->mGroups as $groupEntry) {
print “$groupEntry “;
}
print “ Access Denied”;
print “Allowed users: “;
foreach($cleanedUsersAccess as $userEntry) {
print “$userEntry “;
}
print “Allowed groups:”;
foreach($cleanedGroupsAccess as $groupEntry) {
print “$groupEntry “;
}
exit();
}
?>
March 5th, 2006 at 12:48 pm
hey the blog cuts the tag data and many authors!
sorry
March 9th, 2006 at 7:33 pm
Hey could somebody repost a current working 1.5 version?
-Sean
April 13th, 2006 at 3:58 am
Hello!
We have almost the same thoughts as Michael Kennedy already described. We are using the Mediawiki as a collaboration environment in a design house, which is making projects (products) for multiple customers. It would be perfect if it would be possible to publish certain pages (Product specification, requirements specification, support page, bug tracker, etc) to the customer, but deny all other pages. Basically, customer one should not see pages related to other customers or the pages that are intended for internal use. Therefore, as I see it, the system should deny viewing and editing ‘’’all’’’ pages for certain user belonging to a dedicated group (all customers should belong to the ‘external’ group), except the pages that have this extra tag on it.
e.g. group=external; users=customer1,customer2..
Or even:
Hidden content …
Content to be published…
Hidden content …
I’m not expert in the Mediawiki internals, but it seems to me, that, in order to accomplish this the LocalSettings.php should define an array variable defining all the groups that must go through the extra content processing. If a user belonging to one of the groups accesses a page the page must contain the (or ) tag. If not, the page is not displayed (the browser is redirected to a deny page), if yes, the allowed part of the page will be displayed.
For any other group the tag will be ignored.
Thanks!
May 10th, 2006 at 8:09 am
I have made a group based version of this code, so you don’t have to change every page, if a user is no more allowed to see a page.
See http://blog.pagansoft.de/index.php?/archives/12-Extension-fuer-MediaWiki-Seitenbasierte-Gruppen-Zugriffskontrolle.html#extended for details
Thanks! That was a very cool template for my very first MediaWiki extension.
June 26th, 2006 at 9:53 am
Your code works exactly as it should but there’s one design flaw. You cant restrict the group pages themselves! Any one can add themselves to the group just by editing the page. I know you can restrict the page to just sysops, but this doesn’t scale well if you have multiple sysops and you don’t want all of them to have access to the page.
Any ideas on how we can fix this?
November 9th, 2006 at 3:37 pm
Hi there,
The solution(coding) is quite good. However, if there are 50 users to whom I would like to restrict access to, then I would have to enter 50 users!
I am trying to figure out a simpler solution to restict users for each class of students —that is, depending on which students should be given access as per the course they enroll.
In each class, I would have around 30 students and there are so many classes in the university. It is not possible for the administrator to enter all student names for each class as it is very time consuming and tedious.
I have been trying to figure out a solution for my problem since a few weeks. Does anyone have any suggestions to a simpler code solution?
Thanks.
November 10th, 2006 at 8:30 am
Shilpa,
If you don’t exactly need to use MediaWiki for your class, check out the DFWiki that comes with Moodle 1.5. The ACL that comes with Moodle makes it so you can start a new wiki for each class and control who sees it and who can edit it.
For a classroom situation, it works well. You can also create a read only copy of the wiki and an edit copy that students use. Once the students have improved the wiki, you can incorporate the changes into the read-only wiki and use the new wiki copy for the new class to have an even better starting point.
It’s not the greatest solution for a non-class setting though, so I’m hoping I can get a real ACL solution for MediaWiki to work.
November 13th, 2006 at 4:39 pm
Thanks Tim for ur reply. I will check it out.
March 21st, 2008 at 11:31 pm
Links: http://ms-zithromax.bigplusbig.net/zithromax-dosage-in-children.html
March 22nd, 2008 at 12:01 am
Links: http://fast-phentermine.bigbigband.net/phentermine-shipped-cod-all-states.html
March 22nd, 2008 at 12:30 am
Links: http://ativan-experience.bigbigmail.net/street-value-of-ativan.html
March 22nd, 2008 at 12:59 am
Links: http://viagra-dick.bigcoolweb.net/discount-viagra-online.html
June 8th, 2008 at 3:51 pm
Links: http://vioxx.tophotpop.com/georgia-vioxx-recall.html
July 1st, 2008 at 7:40 am
Links: http://phentermine-prices.ultramanx.com/order-phentermine-online-consultation.html
July 3rd, 2008 at 7:27 am
Links: http://air-transat-flights.partsstraight.com/cheap-air-flights-airline-discount-central.html
July 11th, 2008 at 6:53 am
Links: http://online-telemarketing.yourmegaman.com/map.html
July 29th, 2008 at 5:09 pm
Links: http://ugg-boots.megahotrolex.com/repair-ugg-boots.html
July 30th, 2008 at 6:17 am
Links: fear-of-flying-xanax.html