Summary: A user-based permission granting and authentication module
Version: 2.2.3 (2010-03-03)
Prerequisites: PHP >= 4.3.3 (for having a sufficiently working session support); Cookies enabled
Status: released, stable, maintained (tested with Pmwiki 2.1.11, 2.2.0-beta45)
Maintainer: ThomasP
Users: +3 -1 (View / Edit)
Discussion: UserAuth2-Talk


This is an authorization and authentication module for the pmwiki engine, originally intended to be a reimplementation of the Cookbook.UserAuth module. It provides a flexible way of granting permissions on a per-user basis via a typical web interface, and password or - subsequently - cookie based authentication. The main motivation was to fix the bugs in the former module systematically and on the way introduce the possibility of sharing/delegating administrative tasks (like creating users, assigning them permissions) with other users. See a complete list of changes compared to the former module here. (LDAP support was added in version 2.1-beta2.)

Live showcase

I have put up a live example of this module at A sub admin account can be accessed via username "small_admin", password "pmwiki". It allows access to the admin tool (click "Admin tool" next to the action links), creation of users and unlimited access to groups starting with "Test".



   UPGRADE.userauth2                <- find information about how to upgrade here


Unzip the package file and copy the contents to the cookbook directory. Move the file userauth2/Site.Login to wiki.d/ and userauth2/UserAuth2.EditUserQuickReference to wikilib.d/. Add

 $HomePage  = "Main.HomePage";       // should use dots (instead of slashes) even when using
 $LoginPage = "Site.Login";          // CleanUrls ($EnablePathInfo=1)
 $HandleAuth['diff'] = 'history';

to your local/config.php and adapt the home page setting to your needs. (It is needed for some default redirection.) The login page can be renamed/moved around BTW (provided you adjust the local/config.php), but make sure it is non-editable. The HandleAuth line can be omitted if no designated permission level for accessing the page history is needed.

Upon the first run of the module, an 'admin' user will be created with a default profile containing an empty password. Change this later, e.g. by calling

while logged in as 'admin'. Besides a guest user group will be created, with read-all access (except for the SiteAdmin group) set as default. You can change this as you like. You can also define a group "LoggedInUsers" whose rights are granted--as the name suggests--to all users that are logged in (i.e. are identified to the system with non-empty user name).

That's it. I have put up some help below on how to get the permission setup started. As the module slowly starts to mature, I expect no immediate bugs to be discovered anymore. If there still should be one, or if you have questions/suggestions, leave a comment below or ask on the pmwiki mailing lists (usually pmwiki-users is best). For development related details it might be also useful to contact me directly (email can be found here).


To ensure a defined session expiration behaviour and for various security reasons, this module directly sets the session save path to a sub dir in the userauth2/ dir. (This directory will be automatically created.)


There has been a long-standing failure (reported often for (apparently) Windows PHP5 installations) where the session functionality was broken, in the sense of "forgetting" the login directly after passing the correct password to the wiki. (Thus no actual login was possible.) The problem was known not to be caused by UA2 code and could roughly be drilled down to the session file not being correctly written due to a faulty PHP session support. This problem now seems to be solved, with Jerome reporting that upgrading to PHP 5.2.8 helped (see comment below, 2009-02-12). Please add any relevant observation below to the comments.

Useful markup

To get some login/logout links, the following markup might serve as example:

(:if loggedin:)
* [[Logout ({$AuthId}) -> {$FullName}?action=logout]] \\
(:if ! loggedin:) 
* [[Login -> {$FullName}?action=login]] \\
(:if auth admin :)
[[{$FullName}?action=admin | $[Admin tool] ]]

Simple usage

Setting permissions is done by manipulating the permission tables of the various users/groups. For this call up the admin tool via

while being logged in as admin (or as someone who has admin tool rights). Then, to grant rights specify a list of permission entries in the permission table of the respective user (create a new user first). The common entries take the form


where LL is rd, ed, up or hi, denoting the permission levels read, edit, upload and history. (Here "upload" means that the user may upload files to the dir corresponding to this page, and "history" that she may view the history.) You can also use xx which matches all page related levels. The ggg.ppp is the part specifying for which page the right should be granted. You can use typical wild cards to target a set of pages/groups.

Prepending the whole entry with a '-' (minus) exactly withdraws the right. For this purpose the entries in the permission table are interpreted in the order they occur, with the final applicable entry setting the result.

For example a typical guest user permission table might look like this (this is a suitable permission record for pmwiki 2.2.0-beta58 or above, previous example here)


It makes the whole pmwiki readable, with exception of the 'SiteAdmin' group which is reserved for pages intended not to be publicly available (since pmwiki 2.2.0-beta58). Additionally a feedback page is editable, while the complete Playground group is freely accessible.

Help on options / advanced features

Find documentation on the topics below on the documentation page.

  • How to authenticate against a LDAP server
  • How to set up ip based silent permission granting
  • How to set ip based login restrictions
  • How to change the default redirections after login/logout
  • How to enable/customize persistent logins
  • How to disable/customize brute force attack prevention (enabled by default)
  • What wild cards can be good for
  • How to create personally accessible pages (using {$AuthId})
  • Delegating permission granting / Multi admin setups
  • How to introduce new permission levels for certain actions, like for "publish", "comment" etc.
  • How to change one's own password as a user
  • How to create a new user as a non-admin user
  • How to use the recipe with SSL


If you discover a bug in the system and like to do some debugging, you might consider getting my debugMsg() function (can be found at ThomasP). With this you can use the internally already set up debug facilities.

In general when encountering a bug, have a look at the KnownIssues first, and have a light skim over the mailing list archive to see whether something is said about it already. When reporting, please quote your pmwiki and PHP version.

If you like to contribute to development and have some larger comments, please leave them on UserAuth2-Talk.

See Also

Related modules



Small user survey

I'd like to know who is actually using this module. Just manually count up numbers:

  • new user (first time at pmwiki for no more than 3 months): 21
  • "old" user: 12

(started April 2007)


This space is for User-contributed commentary and notes. Please include your name and a date along with your comment. Optional alternative: create a new page with a name like "ThisRecipe-Talk" (e.g. PmCalendar-Talk). See Discussion at UserAuth2-Talk

The skript works very well - great work! But when I want to login with setting a cookie the following is returned:
Fatal error: Call to undefined function: get_rand_session_id() in [...]\cookbook\userauth2\UserSessionVars.php on line 200 How can I fix it? Tx a lot! Michael November 16, 2007, at 03:04 PM
Fixed it by replacing line 200 in UserSessionVars.php by $randKey = microtime();. It works, but I guess there shall be a more professional soulution. :-) Michael November 17, 2007, at 02:03 AM

Thank you Michael, it is quite astonishing that this error had not been arisen before. (Though I personally use the module currently without cookie authentication.) The function referred to an old setup with a separate session implementation. I have added the missing code (a pure arbitrary choice of mine for a good rand key generator BTW), starting from version 2.0-beta9. See changelog for the new code. ThomasP November 28, 2007, at 12:25 AM

Hope this isn't a stupid question, but where exactly does the permission table content go - in Site.Login, the userauth2 php file, somewhere else? I took a look at UserAuth2.ExampleSetups and it also does not say where one would place the settings. Thanks for any help. -Matt

Log in as admin then go to the admin page by appending ?action=admin to any url

For the user or group you want to give the permission to click on edit.

In the form displayed there is a box Permissions granted by. table content goes here.

I had to think about this, but it works well -Dave

Yes! Thanks for the help, all good now. -Matt

It seems that my '' has bad links all around. Could it be because I set "$EnablePathInfo = 1;" ? All the links on that page are rendered '' or < all dead links. Thanks - Kevin - Profiles

Hello Kevin, the problem should be solved with version 2.0-stable5. The reason for the search links appearing was that $ScriptUrl was unintentionally overwritten by UA2. ThomasP May 27, 2007, at 05:46 AM

I am trying to implement the UserAuth2 and I am having some difficultly. I have my user with admin rights but whenever I type in the password, it displays the "incorrect password" message. It should be the correct password, I say this because earlier I was able to change it from xxxx to yyyy and it was saved successfully. Any ideas?

Hi! This could have many reasons. First it is important to know that "Wrong password" is shown also if actually the user name is wrong, or when the ip address of the client does not match the allowed login ip range (if you have set sthg like this). Can you have a look in the admin profile file to see whether the change has actually taken place? (BTW, let's take it to the pmwiki-users mailing list, otherwise I might not become aware of your answer.) ThomasP July 24, 2007, at 05:41 AM

Hi, I always lock myself out when editing users/groups: "Cannot proceed. This record is locked by someone else for editing. Please try again later.". Because of trouble with my hoster (disturbing error comments) I uncommented all lines beginning with ini_set in userauth2.php (about five around line 210). Could this be the source of the error? peter February 26, 2008, at 12:14 PM

The error message is: "Warning: ini_set() has been disabled for security reasons in /usr/export/www/host...." and from what I understand big part of the cookie game is managed in these 5 lines. Any ideas for work around? peter February 26, 2008, at 12:49 PM

It's not the cookies. The 5 mentioned lines can be discarded. But I found files called after the locked out groups in the userauth2/groupperms folder. They seem to have timestamps. Deleting them solved the problem.

Hello, seems I'm fortunate enough to come along when the problem is already solved. Usually the locks are applied to prevent multiple admins to edit a record of one user at the same time. Usually these locks are deleted upon logout, edit cancel, or simply disregarded if old enough. The question is your case would remain why it did not work in the beginning, but then later.

The ini_set lines adjust the absolute lifetime of the php session files to 24h (rather than 24mins default). Note this is only (the inflated) part of the mechanism, the authorative time management is done in the userauth2.php script "manually" in order to be reliable. (The PHP implementation is prohibitively sluggish with respect to session expiration.) ThomasP March 26, 2008, at 02:41 PM

Hi, after i installed the package I get the following errors..
Notice: Session table unacceptable in /www/global/script/sessions.php on line 88
Warning: mysql_real_escape_string() expects parameter 2 to be resource, null given in /www/global/script/sessions.php on line 108
(plus I dont think I have farms enabled. Im just looking to add basic user authentication to my new pmwiki install)

"Unfortunately", there is no sessions.php in this package, and I have never used the function mysql_real_escape_string(). ;-) ThomasP March 26, 2008, at 02:44 PM

Hi, I'm a little bit confused with the parent and group settings. From my understanding, if you want to create a 'Editor' group, you need to:
  1. Create a user called 'section_a_editor', granter 'admin', with the limited rightsets specified
  2. Create a group called 'secton_a_editor', granter 'section_a_editor', with the same rightsets as above

Later on, you want to create a new editor for section A, you can

  1. Create a user, granter 'section_a_editor', rights '@section_a_editor'

Is it correct? What is the use of 'group' actually? A shortcut to a rightsets?

The use of groups is indeed to provide a way to collect a certain right set and then be able to reference this set from various users by adding e.g. "@Section_A_Editor" to their permission list. It is not necessary to create a dedicated granter for this. The administrator can both create and edit the group "Section_A_Editor" and edit the permission records of relevant users. This should suffice for most of the cases.

The use of the granter field/ multiple granters is to allow more than one person (beyond the Administrator) to set permissions for a single user, while keeping these granting privileges separated. (The "second admin" would and should not be able to change what the first admin set for the user. Obviously.) This way one can realize real delegation of admin work, e.g. set out responsibility areas in the wiki (e.g. page groups) which are governed by different persons. ThomasP July 10, 2008, at 07:56 AM

Hey, is there a way for users to register themselves?


Ben - May 11, 2008, at 03:14 AM turned dot 111 at gmail dot com

No, unfortunately not, at the moment. There was a solution once for UserAuth (the former version) (not compatible or reusable), which might give some insights into what is useful/necessary to be implemented. I have not anymore all these aspects on my mental screen at the moment. (But for example, to avoid bots registering, some captcha mechanism would be necessary.) To think loudly, my spontaneous idea would be to use indeed the Pmwiki forms, together with a function called by dedicated markup to actually add the user. I'm not proficient with Pmwiki forms, but would write the second part if the interest is still there. ThomasP July 10, 2008, at 07:56 AM

I cannot figure out what page a user should go to in order to update their password. (I set a user with the pw permission, but don't know how that user would actually go about changing things, since I don't want to give them permissions to the main admin page.) Thanks in advance... the plug-in overall is quite cool.
Answered my own question. Append ?action=pwchange to a URL. Now, where to put this in the docs... (done, ThomasP October 02, 2008, at 12:53 PM)


Hey, is there a way to reset the admin password afterward (I forgot it...)?


Plog - July 19, 2008

Hello, yes, though with some dirty editing. Passwords are stored among other things in the profile of the user, see userauth2/profiles. In the serialized PHP array, find the "password" field and replace the value (with me a 34 character string starting with $) by the output of the PHP crypt function (use the ?action=crypt to get that for your newly chosen password). ThomasP

October 02, 2008, at 12:53 PM

I love this recipe, but I found one issue and me being a noob I must have missed something. I don't see where to add users anywhere. Did miss something somewhere?

Thanks AJ - Roctober, 29 2008

When logged in as admin, go to the admin tool and scroll down to the end of the user list. There should be a button "add user" as last line in the table. Furthermore, in the extended use of the module, also certain non-"super-admin" users can add users (which will be seen as a kind of their children). For users to be allowed to add (create) users, they will have to have a cu entry in their permission record.
On the other hand, you might also have thought of users signing up to the wiki themselves. This is currently not possible. ThomasP December 23, 2008, at 09:02 AM

I have encountered a problem with this unit following an upgrade Easyphp (EasyPHP 2.0b1). Managing sessions did not work.

The problem was the php version 5, which was bugged, I updated with the latest version of EasyPHP which includes the PHP 5.2.8 release, now the problem is resolved.


February 12, 2009, at 11:42 AM

Hello, I attempted to re-install a new copy today after having used UserAuth2 for quite a while now. Installing a fresh copy gave me the following:

Parse error: syntax error, unexpected '{' in .../cookbook/userauth2/UserSessionVars.php on line 69

I am running pmwiki version 2.2.0. Any thoughts, or perhaps a solution? Any help is much appreciated, thank you in advance for your time!

-Matt, Feb 12, 2009

Hello, the reason will be the "try" statement (in UserSessionVars.php on line 69), which does not seem to exist, at least not in PHP4. (Well, one should never copy code untested from somewhere ;-) Can you do my the favour and try to run the code with the "try catch" wrap removed (but of course with the try block kept in)? I have not got it running here on Windows but Linux, therefore the error. ThomasP February 15, 2009, at 07:52 PM
Hello, I am running PmWiki 2.2.0 with UserAuth2 2.2.1 on a Sun Sparc station with SunOS and I am getting the same error as the one mentioned above. I have deleted the whole code block in UserSessionsVars.php labeled "// MS-Windows platform?" including the "if (@class_exists('COM')) {" block and including the "try .. catch" block and it runs fine now. PaulWiegmans 17 feb 2009, 15:24
Many thanks. I have meanwhile taken out the "try {} catch", but will leave the "class_exists()" inside (awaiting more feedback before taking further surgery action). ThomasP September 02, 2009, at 08:57 AM

When I paste in the example (if) conditional code to get login/logout links, it just outputs the conditional block on my pages. Does this code not go in my tmpl file? Or do I need to wrap it in something else?

JM - March 8, 2009, at 2:42 PM

Hello JM, the example code listed above is wiki code, so it has to be put on some wiki page (e.g. preferably in Site.SideBar or Site.PageActions to have it always displayed). ThomasP September 02, 2009, at 08:24 AM

Can you please consider optionally adding something (no matter how simple it is) to enable users to automatically register themselves in LoggedInUsers group?


[Just as side note ahead: LoggedInUsers is just a special virtual group that is automatically containing a user once he is actually logged in. It has nothing to do with whether you have an account ("a login" in lax wording) at the wiki site. However, clearly, enabling users to have an account and making them to login finally will "get them" in the LoggedInUsers group.]

Feature list of what might be essential: ThomasP September 02, 2009, at 09:28 AM

  • profile information storage (mainly email)
  • captcha (at least preparation)
  • email verification needed?
  • admin approval of new registrations

Is it possible to import users from original userauth script. Maybe read the .htpasswd file and create groups/users from it.

Thanks Nigel May 27, 2009

Originally left open "as exercise" for volunteers. :) The .htpasswd file parsing should be easy, and the user profiles in UA2 are flat files easily inspected for their content. (They are PHP arrays serialized; the filename is the username.) No magic here. There is a chance that passwords even can be kept intact (if the system's crypt() function is used); otherwise one will have to create new temp ones and then require the users to change it once. ThomasP September 02, 2009, at 08:24 AM

I would suggest we have a voting at this very place: (everyone needing this please add a star below, possibly with some name and date)

  • Nigel, 05/2009

  • In the latest version (:loginform:) doesn't parse when accessing the wiki via http://www.mysite.example/index.php. It only starts parsing as soon as you click on a link which makes the url being shown as http://www.mysite.example/index.php?n=MainGroup.MainGroup. Is there a solution?
  • And as well in the latest version the cookie fatal error I mentioned on Nov 17 2007 and has been fixed in subsequent versions occurs again.

Thanks for fixes and/or ideas. Michael June 18, 2009, at 12:32 PM

The "(:loginform:)" syntax in this recipe (and its predecessor) has a special way of being injected into the Pmwiki parsing mechanism. This may (obviously, but unfortunately) result in sometimes unwanted behaviour when aspects of the Pmwiki engine change.

To actively clear this problem, can you state what version actually made the problem observable? ThomasP September 02, 2009, at 09:16 AM

Thanks for your answer. I'm using version 2.2.2. of UserAuth2, as well as version 2.2.2. of PmWiki. Michael September 11, 2009, at 11:41 AM

Hi, I am trying to use the UserAuth2 together with LDAP. Unfortunately in our company we use user names like name-Nr. like name-1. The actual code don't accept the - sign for user names - so I started to modify the code for testing. I found out that I have to change the RegEx match variables on different places like $PermholderRegExp, $PasswordRegExp, $AbltsRegExp and return preg_match('/^[a-zA-Z][a-zA-Z0-9\_\-]*$/', $user); Would it be possible to place the RegEx-Variable on one place? even better so that the Variable can be overwritten in a config file?

An other question. Is there a possibility to configure the code that the admin user works with the internal authentication and all the other users with LDAP?

Thank you very much! Markus October 05, 2009

Firstly my webserver stopped working after the disk got full. After emptying some files to make space and restarting apache, I couldn't login to my wiki with UserAuth2. Site.Login responds with "Server temporarily unavailable". I am getting this error in /var/log/apache2/:

 [Wed Jun 15 11:11:26 2011] [error] [client] PHP Warning:  
 fgets(): Length parameter must be greater than 0 in 
 on line 822, referer: [(approve links)

What is going on? How can I see the messages that are supposedly written tot UA2Errorlog? PaulWiegmans June 15, 2011, at 07:25 AM

It is a great recipe, I discovered it for JITS which is also very convenient.

Unfortunately, despite having userauth2.2.3 (2010-03-03) and PmWiki 2.2.36, both latest versions as of today, I do not have pagelist working, neither directly nor as search result. I read in UserAuth2-Talk that it was fixed a while ago, I even read through the mailing comment yet I can not figure out why it is broken and how to make pagelist work again.

Utopiah February 09, 2012, at 10:49 AM

According to the installation documentation

"Upon the first run of the module, an 'admin' user will be created with a default profile containing an empty password. Change this later, e.g. by calling "

My problem is that it never created a profile folder and admin page anywhere in my installation. I cannot log as admin and I cannot change the admin password because there is no profile page. Maybe there is a right restriction on the server that prevent the script from creating a profile directory. Is there a way to force the creation of the admin profile, else where should be located the profile folder and is there a sample admin profile file somewhere in case it does not create one.

Thank You. Larienna, November 15th, 2012.

Update (nov 15th 2012): I finally found the profile directory with the admin file (it was under "cookbook/userauth2/profiles"). I replaced the "password" string with an encrypted string like previously explained for resetting the password. Then I tried logging as admin with password and it does not work. I tried with a clear password and it still does not work.

Figured out how to reset the admin password. Delete the admin file in cookbook/userauth2/profiles This will reset the admin password to blank. Goto and this will let you enter a new password.

An addendum to Remark 1:
You can override this session_save_path behavior by adding the following line to config.php before including the cookbook/userauth2.php:

## Prevent UserAuth2 from changing the default session_save_path
$UA2SessionSavePathDir = session_save_path();

The problem I was experiencing is that PHP is unable to use a directory as the session_save_path if that directory is not owned by the web host, and this was not a sane option with my wiki stored on an NTFS-3G mounted Ubuntu file system (It runs in Apache2 on Linux, or IIS if booted to Windows 10.)

It is also generally useful to be able to configure this setting, so as to ensure the session data storage is on a file system that is good for quick reads and writes of lots of small files.

~~ Damien Palmer July 13, 2017, at 02:22 PM


This is a patched version of userauth.2.2.3.tgz that fixes some issues that are caused using UserAuth2 on PHP 7.2. These issues cause numerous warnings to appear in de Apache2 error log like this:

	PHP Warning: Use of undefined constant someidentifier - assumed 
	'someidentifier' (this will throw an Error in a future version of 
	PHP) in {file} on line {number} 

and also:

	PHP Warning:  count(): Parameter must be an array or an object that 
	implements Countable in {file} on line {number}

These warnings are all caused by a old style of PHP programming in UserAuth2 where sometimes strings where passed without quotes. When this happens, stricter type checking introduced in PHP 7.2 causes many warnings to be logged in Apache2 error log.

define(UA_ADMINTOOL, '2.0'); changed to: define('UA_ADMINTOOL', '2.0');

if (!function_exists(microtime_float)) { changed to: if (!function_exists('microtime_float')) {

Disabled some lines of debugging code at lines 330-334 in userauth2.php.

~~ PaulWiegmans Apr 27, 2019 at 16:45

User notes +3 -1: If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.