AuthUser

Summary: PmWiki built-in user authentication system using user names and passwords
Version: pmwiki-2.3.31
Prerequisites: built-in script
Status: Stable
Maintainer:
Users: +5 (View / Edit)
Discussion: AuthUser-Talk
Categories: Security

NOTE: Do not confuse AuthUser, with the recipe UserAuth. AuthUser is part of the standard distribution of PmWiki (see PmWiki.AuthUser). Cookbook:UserAuth is a recipe which is not part of the standard distribution.

NOTE: In local/config.php Be careful to specify any AuthUser['... or DefaultPasswords['... config statements BEFORE the line include_once('scripts/authuser.php');, otherwise nothing will work (in short)! - rupee June 11, 2006

Question answered by this recipe

How can I add user-based (rather than merely password-based) authentication to my wiki? I want PmWiki to prompt for both a user name and a password when someone attempts certain actions on protected pages, groups or the whole site.

Answer

Starting with version 2.0beta39, PmWiki includes an authuser.php script. This Cookbook recipe describes how to use it to add user-based authentication to your wiki.

Some of the material on this page is outdated. See PmWiki.AuthUser for an up-to-date description.

The authuser.php script changes PmWiki's password page so it prompts for both a user name and password rather than just a password. If a user name is supplied, the user will be authenticated using a supported authentication scheme.

Implement user-based authentication with these three steps:

  1. Provide a list of users and their associated passwords.
  2. Include the authuser.php script.
  3. Apply password protection to pages, wiki groups, or the whole site.

Providing User Names and Passwords

You can provide username/password pairs in a number of different ways, for example by listing them in config.php or by using a passwd-formatted text file. Support for LDAP was added in PmWiki 2.0.beta55 and support for Active Directory was added in PmWiki 2.2.0. Future support is planned for other authentication schemes such as Linux-PAM.
There is also Cookbook adding OpenID support. See Cookbook.AuthUserOpenId

Option: User List in config.php

You can create a list of users with their associated passwords by setting the variable $AuthUser in local/config.php. $AuthUser is an array of user/password pairs, which can be added in config.php like

    $AuthUser['bart'] = pmcrypt('bartspassword');
    $AuthUser['nancy'] = pmcrypt('nancyspassword');

Option: User List on Site.AuthUser

There should be documentation here on how to use AuthUser to set password permissions. It's a very easy way to do this. Adding your passwords to this page is generally easier than editing the config file.
If you use this page to set passwords (very convenient), you must logout and then log back in before any changes will go into effect. This is important to remember!

Option: Passwd-formatted File

You may also specify a passwd-formatted file (usually called .htpasswd on Apache servers) by including a special "htpasswd" user and the path to your passwd-formatted file. If you have usernames and passwords in a file called .htpasswd in your local/ directory, you will write:

    $AuthUser['htpasswd'] = 'local/.htpasswd';

$AuthUserHtPasswd = 'local/.htpasswd';

To access an .htpasswd file which is stored outside of your web structure, you need to specify the entire path:

    $AuthUser['htpasswd'] = 'C:/path/to/directory/.htpasswd';

You can use user/password pairs in config.php and a password file together.

Option: LDAP

Put the URL for the server in $AuthUser['ldap'], as in

    $AuthUser['ldap'] = 'ldap://ldap.example.com/ou=People,o=example?uid';

Option: Active Directory using LDAP

Put the URL for the server in $AuthUser['ldap'] without path info, as in

    $AuthUser['ldap'] = 'ldap://ldap.example.com/';

Option: Password from MySql or Postgres Database

Use the AuthUserDbase recipe

Option: XML-RPC Authentication

I used dbauth.php as a template for XML-RPC authentication, in case anyone has similar needs. Worked out great: I just removed the database arguments and replaced with XML-RPC calls; if successful, add the $userName and $password to the $AuthUser array. Make sure you use the pmcrypt() function on the password before adding to array; the dbauth.php script does not.

Invoking authuser.php

Install the authuser.php script by setting in local/config.php:

    include_once('scripts/authuser.php');

or if you run a WikiFarm:

    include_once("$FarmD/scripts/authuser.php");

The order of the lines matters. Define users with $AuthUser definitions first, then include the authuser.php script. A section of your config.php script might look like this:

    ## Define usernames and passwords.
    $AuthUser['bart'] = pmcrypt('bartspassword');
    $AuthUser['nancy'] = pmcrypt('nancyspassword');
    $AuthUser['htpasswd'] = 'local/.htpasswd'; # A passwd-formatted file

$AuthUserHtPasswd = 'local/.htpasswd'; # A passwd-formatted file

    ## Enable authentication based on username.
    include_once('scripts/authuser.php');

Setting User-based Restrictions for pages and groups

Now you can protect single pages (or whole groups via GroupAttributes) using ?action=attr (see Passwords Admin) by adding "passwords" of the form id:username that look like this, in addition to plain passwords:

 foobar barfoo                # anyone who knows either password can do this
 id:bart                      # only "bart" can do this
 id:bart,nancy                # either "bart" or "nancy"
 id:*                         # anyone with a valid username/password (any logged-in user)
 foobar id:bart               # only "bart" and anyone who knows the password "foobar"
 foobar barfoo id:bart,nancy  # "bart", "nancy" or anyone who knows either password

You can also use similar "passwords" in your local/config.php file. If you want a site-wide edit restriction, allowing only Bart and Nancy to edit pages, you can write:

    $DefaultPasswords['edit'] = 'id:bart,nancy';

If you have individual users to whom you want to give site-wide edit access, and you want to have a "generic" password (eg N. Herber's Zebra) available to give out for the purpose as well:

    $DefaultPasswords['edit'] = array(pmcrypt('Zebra'), 'id:*');

To allow anyone with a valid username and password to edit pages, you can set:

    $DefaultPasswords['edit'] = 'id:*';
  • This recipe was last tested on PmWiki version: 2.0.beta39
  • This recipe requires at least PmWiki version: 2.0.beta39
Again, there should be information here about how to define password groups. Put @orange: Name1,Name2,Name3, etc. in Site.AuthUser page. Then on the attributes page put @orange and all three users are authorized. Not sure if this can be done in a config file or a htpasswd file.

Notes and Comments

Note that username/password pairs are in addition to PmWiki's system, which does allow password protection for individual pages, whole groups, or site-wide, and allows to set protection for read, edit, upload and attr actions respectively. Defining a username plus password does not give that user any access rights automatically. These need to be set via ?action=attr for individual pages or groups, or site-wide through the $DefaultPasswords variable. Page attributes take priority over group attributes, and both over default passwords set in config.php. Only $DefaultPasswords['admin'] has priority over all others (see Passwords).

About Passwd-formatted Files

Passwd-formatted files are text files where each line contains a username / encrypted-password pair. The username and encrypted password are separated by a colon, so a typical .htpasswd file looks like this:

     Jack:vK99sgDV1an6I
     Jill:Q1kSeNcTfwqjs

Use ?action=crypt in the browser's address bar (once you are logged) to generate the encrypted strings of passwords. You may notice that the same password generates a different result if you encrypt it again. That's explained here.

You can add users to an existing .htpasswd file manually by editing the file, or at a system prompt using a special system command:

     htpasswd -n someuser >>local/.htpasswd

The htpasswd command for creating and updating user authentication files is distributed as part of the Apache web server.

Your system-wide /etc/passwd or (more likely on most modern systems) a local copy of your /etc/shadow file are passwd-formatted files that may be used to hold the usernames and encrypted passwords.

Setting the Author Automatically

If you want to assign the username entered at the prompt to the $Author variable so it appears automatically in the Author field of the edit form, you can add to config.php:

## If there's no Author yet, use the verified identity.
include_once("$FarmD/scripts/author.php");
if($AuthId && !@$_COOKIE[$AuthorCookie]) {
  $Author = $AuthId; setcookie($AuthorCookie,
    $Author, $AuthorCookieExpires, $AuthorCookieDir); }

This way the author's name can be changed by the author, but it's pre-set for convenience when they log in. The RequireAuthor Cookbook page explains how to enforce author tracking.

Using the authenticated identity as author name is the default behavior starting with version 2.1 beta26.

Duplicate Password Problems

Something that can cause confusion is where an admin or attr user share a password.

For example a group of pages can be made editable by the administrator by setting the GroupAttributes password to: id:admin. However if user fred has the same password as admin (or maybe if there is an MD5 hash collision) then fred will also be able to edit pages in this group because his 'admin' level password has taken priority over his lack of privilege.

It seems that pmwikiauth and authuser check the username/password pair initially to confirm identity but then are interested in passwords as in the original pmwiki philosophy.

To summarize, administrator passwords take precedence over user page or group privileges. Not necessarily a bug but something to be aware of.

davidof Mon Sep 5 08:45:04 RDT 2005

Of course the way around this is not to set any passwords, just enable admin and edit functions based on id:membername. The password authentication only works if you set passwords. :) Caveman September 14, 2006, at 09:37 PM

Logout, Login

In pmwiki ~beta 54 there is a minor bug. After logging in with a wrong user, you have to close the browser, or logout, otherwise you can't login with a valid user.
What ever it's practial to be able to logout with ?action=logout
see: LoginLogout

session expired AuthUser seems to handle this problem correctly. Password is prompted and action is continued as expected.

In UserAuth#SessExpired session expiration is very cubersome, and one has to be extremly carefull to have no dataloss

PatrickOgay August 26, 2005, at 01:22 PM

Global and local $AuthUser definitions in wikifarms

[hint from pm]
All $AuthUser settings have to occur before including authuser.php, otherwise they don't take effect.
If you like to define users locally in local.php it can be done like this:

#farmconfig.php
# do farm config settings here
# ...
include_once('local/config.php');          # load per-field settings

$AuthUser['pmwikif'] = crypt('pmwikif');   # set up authuser
include_once('scripts/authuser.php');

otherwise you have to include authuser.php after the definitions locally.
It works!!
PatrickOgay August 26, 2005, at 01:22 PM

Wildcard names, common password

I have a read-restricted wiki where I want to allow any user who knows a shared password (Zebra) to have read access. But I also have several users already in an Apache .htpasswd file, and I would like their passwords to work too. In other words, they don't have to learn yet another password. This is accomplished by the following line in config.php:

    $DefaultPasswords['read'] = array(pmcrypt('Zebra'), 'id:*');

This tells PmWiki to allow in anyone who authenticates against the .htpasswd file (id:*) or who enters the password "Zebra". Unfortunately, authuser.php currently does not force the user to enter a username. It would be nice if it did.

 NeilHerber

Using AuthUser with Apache Basic Authentication (BA)

I have a wiki that runs inside an Apache BA protected realm, so by the time the user reaches the wiki, they have been authenticated. I do not want them to have to re-enter their passwords, and I want to be able to control access to pages by password groups. As I write this, AuthUser is not able to read Apache .htgroup files, but AuthUser does have its own group mechanism. Getting the two to work together requires this addition to the wiki's config.php file:

 ## turn on the PmWiki authentication
    include_once("$FarmD/scripts/authuser.php");
 ## if someone has authenticated using Apache BA, then use that for local auth
    if (@$_SERVER['REMOTE_USER']) {
        AuthUserId($pagename, $_SERVER['REMOTE_USER']);
    } elseif (@$_SERVER['REDIRECT_REMOTE_USER']) {
 ## if PHP is installed as CGI instead of an Apache module, then REDIRECT_REMOTE_USER
 ## contains username instead of REMOTE_USER
        AuthUserId($pagename, $_SERVER['REDIRECT_REMOTE_USER']);
    }

Now you can set up password groups on the Site.AuthUser page (it has examples already on it). Neil Herber April 06, 2006, at 09:12 AM

Use of group authorization?

For managing large numbers of users, it is very desirable to have the ability to define access rights based on groups, which could be defined in a standard .htgroup file. The syntax above could be extended from id:username for individual permissions, to include group:groupname for providing a specific permission to an entire group. shi

The ability to manage groups is added in 2.1.beta8. --Pm

Merge with UserAuth?

I moved this discussion to 00748 to for easier tracking and all the other advantages of PITS. --Henning June 02, 2006, at 10:29 AM

Interface with existing Authentication Process

This function is great, it was very easy to adapt our SingleSignOn process to pmwiki AuthUser. Also I found an easy way to display a warning message to an authenticated user, explaining that they do not have authority to edit someone elses pages. If someone is interested I could explain in details

please do!

Also I would like to know where to look to make userid control more flexible, like using regexp for instance. Our logon is structured, 999department999, if we could modify to make id:*department999 or id:*department* it will be great. Isidor

More explanation of LDAP integration

I would love to see a better explanation of the LDAP possibilities of AuthUser, I was using another wiki engine before (dokuwiki) which has very nice, well-documented LDAP integration. When I tried to follow the ldap suggestions in AuthUser, I get script errors. I think that the limited explanation of ldap addressing:

$AuthUser['ldap'] = 'ldap://ldap.example.com/ou=People,o=example?uid';

doesn't work in my situation. -

LDAP and multiple containers

The line used to define the ldap server variables

$AuthUser['ldap'] = 'ldap://ldap.example.com/ou=People,o=example?uid';

worked great in my case until I realized that some of my users fit into ou=People and some of them were ou=Otherpeople - separate containers for different groups of users. In order to make this work you need to use the subtree instead of specifying a particular container. I was able to use the following line:

$AuthUser['ldap'] = 'ldap://ldap.example.com/o=example?uid?sub';

There are probably instances where you wouldn't want to use this, for example if there were containers you didn't want to include, but it doesn't work to simply list multiple containers, so this seems to be the only option. JonHaupt


Active Directory Authentication

As of Version 2.2.0 (2009-01-18)

  • Authentication using Active Directory is now simplified. In Site.AuthUser or the $AuthUser variable, set "ldap://name.of.ad.server/" with no additional path information (see PmWiki.AuthUser for more details).

In config.php enter your LDAP server like so:

$AuthUser['ldap'] = 'ldap://ldap.example.com/';

Note that when logging in you might need to include your domain as in:

Username: mydomain\myusername

User-ability to change passwords

I doubt this exists, but thought I would ask. Is there an easy way to allow the user to change their password while they are logged in? I'm using a password-formatted file if that makes a difference. Thanks! -joe

Try Htpasswd Form. It can do this. Caveman

Authentication Sessions and Farms <- IMPORTANT!

It seems that once you've logged into one PmWiki using AuthUser, you have access to all Wiki's in that farm. Is there any way to limit the login session to just one Wiki? Thanks! -joe

PmWiki uses PHP sessions to keep track of authentication/authorization information, and by default PHP sets things up such that all interactions with the same server are considered part of the same session.
An easy way to fix this is to make sure each wiki is using a different cookie name for its session identifier. Near the top of one of the wiki's local/config.php files, before calling authuser or any other recipes, add a line like:
session_name('XYZSESSID');
You can pick any alphanumeric name for XYZSESSID; for example, for the cs559-1 wiki you might choose
session_name('CS559SESSID');
This will keep the two wikis' sessions independent of each other.
Another way to do is is to create a different group per farm. That is, if your site has farms "strawberry" and "orange" then your groups would be thus:
  • @editorStrawberry
  • @editorOrange
Another way is to place the following line in each field's config.php file so each field will have a unique cookie prefix.
$CookiePrefix = substr($tmp = md5(__FILE__), 0, 5).'_';
Only the session name approach really separates things fully. The user group approach isn't very clean, and somehow I don't think the $CookiePrefix approach will work at all.
Another (likely) approach will be to move the session files themselves into a separate directory for each wiki. This has some other small advantages, especially on Windows servers.--Pm

Linux-PAM

Quick hack to add PAM support. The usual security-warnings apply.

  • requires PHP-Extension pam_auth. There exist RPMs, but this module is so old, it collides with the deprecation of call-time pass-by-reference in PHP5 and throws a warning. I fixed that by boldly commenting out lines 205..208 in pam_auth.c.
  • in config.php add:
    • $AuthUserFunctions['pam'] = 'AuthUserPAM';
    • $AuthUser['pam'] = 'wiki' 'wiki' being the desired name PAM-servicename
  • add the function AuthUserPAM somewhere appropriate (config.php works, but is probably the wrong place)
    function AuthUserPAM($pagename, $id, $pw, $pwlist) {
      foreach ((array)$pwlist as $f) {
        ini_set("pam_auth.servicename", $f);
        $error = "";
        if (pam_auth($id, $pw, $error)) {
          return true;
        } else {
          #echo $error;
          return false;
        }
      }
      return false;
    }
    

Adding a login/logout link to your wiki

This is my first contribution to PmWiki so bear with me if I'm following the wrong procedure, but this appears to be the way it's done. It is really easy to add an automatic login/logout link to your wiki that will show up on all pages. (I saw above where this was requested). If you add the following lines to the Site.PageActions page, it will display a log in link if there is no username and a log out link if there is. This should be easily modified for wikis that do not use AuthUser.

(:if enabled AuthId:)
* [[{$FullName}?action=logout | Log Out {$AuthId}]]
(:if !enabled AuthId:)
* [[{$FullName}?action=login | Log In]]
- Sam

Also have a look at DynamicPageActions

See Also

Contributors

Comments

See discussion at AuthUser-Talk


Category: Security

User notes +5: 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.