+++ /dev/null
-
-Authentication in ewiki
-¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
-If you'd like to restrict usage of your Wiki based on a user system and some
-sort of permissions, then you may want to use the EWIKI_PROTECTED_MODE, which
-enables additional access granting. (This is really optional, and won't have
-any impact on the speed of ewiki if left turned off.)
-
-The whole _auth interface stuff was implemented with flexibility in mind, to
-allow ewiki to reuse any existing user authentication scheme already working
-for yoursite (or used in the container CMS surrounding ewiki). That is why
-this all will look complicated at a first glance.
-
-While it is recommended to use the _auth interface for combination with an
-existing user database (which most always requires to write your own plugin
-to connect it with your user management system); it is for most people also
-often satisfactory to just use one of the ewiki internal user database and
-permission plugins that come as examples inside of the plugin/auth/ subdir.
-You may want to give the user- and administrator-friendly UserRegistry plugin
-a try if you don't already have a working user management system.
-
-
-Leaving ewiki_auth() alone
-¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
-If you just need a project internal Wiki or have only a small group of
-active contributors, then you will often find it easier to just restrict
-your Wiki using your Web servers .htaccess and .htpasswd method instead
-(or see "fragments/funcs/auth.php" for the simpler inline solution).
-
-And often your restriction desires may be matched by the two-wrappers method
-described in the main README file - one public read-only Wiki view, and one
-password-protected access for contributors.
-
-
-interfaces
-¯¯¯¯¯¯¯¯¯¯
-The auth/ plugins are chained with the ewiki_auth() function, and restrict
-access to the Wiki pages based on {meta} data or actions. The authentication
-scheme is modular and divided into the thress basic abstractions / hooks:
-- ["auth_perm"] is the main plugin function to check for access permission
-- ["auth_query"] combines the user authentatication and login form printing
-- ["auth_userdb"] can be used to retrieve a user entry or to verify passwords
-
-
- ewiki_auth()
- ¯¯¯¯¯¯¯¯¯¯¯¯
- Is called throughout the main ewiki script to request minimum
- permissions for the current $action and requested $page. This function
- chains to [auth_perm] and [auth_query] plugins to do its job. This
- function then just returns a boolean, stating if the permission plugin
- granted access.
-
-
- ewiki_auth_user()
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Queries all ["auth_userdb"] plugins (multiple may be there) for the
- given username and password, and returns (true) or (false) after
- comparing against the database entries` password fields.
-
- This function additionally sets $ewiki_auth_user if the password
- matches, and also $ewiki_author if it wasn't yet.
-
-
-Variables
-¯¯¯¯¯¯¯¯¯
-$ewiki_author
- is only informational, but stored in each pages {author} database entry
- field. It is not required to have this variable set, it is just used as
- beatification for the database entries. If it was not set, then still IP
- addresses appeared in the {author} field of edited pages.
-
-$ewiki_auth_user
- on the other hand is used in some of the distributed auth plugins to
- state that a user already was authenticated correctly. So this variable
- is not necessary, just a convinience interface to work around the
- completely functions-based _auth API.
-
-$ewiki_ring
- could be used to allow permission granting from outside of ewiki,
- without writing any custom(ized) ewiki _auth plugin.
-
-
-ring levels
-¯¯¯¯¯¯¯¯¯¯¯
-The so called "rings" are an optional simplification inside of the _auth
-functions. Usually pages in ewiki are accesses pages using its name and an
-action parameter, but it would to too much overhead to base permission
-granting on both. So plugins like "auth_perm_ring.php" map $action/$id's
-down to following "ring levels" to compare it against the current users
-privilige level:
-
- 0 - is for "ADMINISTRATORS", allows actions like admin/ or control/
- 1 - means "MODERATOR" functions, like delete/
- 2 - for ordinary users or "EDITORS", which includes edit/ and upload/
- 3 - "GUESTS" can only view/ pages or view links/ and info/
-
-While the "ring levels" are the built-in way to decide if the current
-request is to be allowed or not, it is NOT the only possible. One could
-still write a plugin, that completely skips the "$ewiki_ring" and bases
-access granting on something completely different. However the ring levels
-are also the default in the userdb plugins, and it is believed to be
-satisfactory to have just four privilige groups/ levels, because otherwise
-the user database needed to contain a bit mask or list of $actions which
-were allowed for each individual user - what surely would be overkill. So
-even if you tie an ewiki_auth plugin together with your already existing
-user database, you may want to reduce it down to just these four permission
-steps.
-
-The $ewiki_ring variable makes it therefore also possible to connect your
-existing userdb with ewiki without writing a customized ["auth_query"] or
-["auth_userdb"] plugin, because if you just enable the _PROTECTED_MODE
-and load 'auth_perm_ring.php', then $ewiki_ring decides about access
-granting. So all you needed to do from within 'yoursite.php' was to set
-$ewiki_ring to 2, and sporadically to 1 for a few "moderator users".
-
-
-ewiki_auth plugin hooks
-¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
-The ewiki_auth() function lets the ["auth_perm"][0] plugin decide about
-access granting, if it finds one. It also calls the first ["auth_query"]
-plugin before, and after the ["auth_perm"][0] returned false (but then
-forcing to print a login form).
-
-The ["auth_userdb"] plugins are not called directly from within ewiki_auth(),
-but they get activated by ewiki_auth_user() which itself is called by some
-["auth_query"] plugins (but they do not need to do this, if they know a
-better way).
-
-But please read the following plugin hook explanations first, if you go to
-write your own customized ewiki_auth plugins:
-
-
- $ewiki_plugins["auth_perm"][0] ($id, &$data, $action, $ring, $forcelogin)
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Is called from within ewiki_auth(), and should return a value of 1 or 0
- if permission is granted. The plugin function should determine this by
- evaluating the current user name.
-
- The ["auth_perm"] plugin is itself responsible for retrieving the
- current username and fetching associated priviliges; but at least the
- user name can usually be found in the global $ewiki_auth_user or
- $ewiki_author (previously used therefore) variables. And for the
- "associated priviliges" the plugin could just concentrate on comparing
- an already defined $ewiki_ring (which eventually was set by a previously
- called ["auth_query"] or ["auth_userdb"] plugin) with the currently
- requested one in the "$ring" parameter.
-
- Often an ["auth_perm"] plugin will want to just look at the $action
- parameter to the currently requested page $id to make its decision
- (not all users should be allowed all $actions). However often it is
- easier to first map down the $action/$id parameters to a smaller set
- of privilige levels (like the 4 ring levels, how the 'auth_perm_ring'
- plugin does).
-
- If a perm plugin however is called with a $ring level request (this is
- the $ring variable is not NULL or false), then it MUST also take it into
- account (besides any other calculations on permission granting it
- already did).
-
- The $data parameter contains the internal array of the current WikiPage
- (as usual), and an ["auth_perm"] plugin could of course also use the
- {meta} field to store access granting informations (the owner name or
- even a password). Eventually the $data parameter is empty or only
- requires a few fields; then it may be desirable for the perm plugin to
- refetch the full database entry via ewiki_database("GET") before
- anything else. An appropriate check for this case was for example
- "if (count($data)<=5)".
-
- If the ["auth_perm"] plugin detects that access is to be denied, then
- it should put a failure message into $ewiki_errmsg.
-
- One could also write an complete ewiki_auth() replacement using
- this plugin hook, as all parameters for the original are passed
- over and only the boolean return value counts.
-
- Note: The default ["auth_perm"] plugin ('.../auth_perm_ring.php') only
- associates those "ring levels" to the different wiki $action tasks, and
- all real user authentication is done inside "auth_query" - but this is
- not required, and it's up to your fantasy to do it in a different way
- (separate login page and [auth_perm] just querying cookies for example).
-
-
- $ewiki_plugins["auth_query"][0] (&$data, $login)
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Is also called from within ewiki_auth() whenever the current users name
- is required and/or a login form could be printed into the current page.
-
- The fourth param $login (boolean) tells whether a login form should be
- printed (or some other mystic authentication should be started). This is
- important because $login=0 means to just check for a username and the
- password which may be currently already present in the httpd/cgi
- environment (in a Cookie for example).
-
- With $login==1 the plugin is asked to return a login <form> by writing it
- into the $ewiki_errmsg variable (unless you do some exotic authentict.
- like http AUTH or access granting based on IP addresses). One could also
- put a failure notice into $ewiki_errmsg.
-
- An $login>=2 on the other hand can be used to explicetely enforce printing
- of the login <form>, even if an user was already logged in. (This then
- becomes the re-login hook).
-
- If you then retrieved a $username and $password inside your auth_query
- plugin (from wherever and regardless if $login=0 or $login=1), then
- your ["auth_query"] plugin should immediately compare it against a user
- database.
- To comply with the rest of the ewiki auth plugins, you should do this
- by calling ewiki_auth_user($username,$password) - which then just returns
- true or false, if the retrieved name and pw match anything inside of any
- registered user database. ewiki_auth_user() will then set $ewiki_ring,
- $ewiki_auth_user, $ewiki_author if the queried database contained that
- informations. Leave the $ewiki_errmsg alone if you let ewiki_auth_user()
- check the $password.
-
- You could of course let your ["auth_query"] plugin do all that work
- (comparing a $username and $password against an internal list, and
- setting $ewiki_ring when possible) - some people may find this far
- easier than chaining to ewiki_auth_user() or so, and this would allow
- you some more flexibility and reduces complexity.
-
- This function doesn't need a return() value - it is not evaluated. If
- you want to return something or inform some other parts or plugins, then
- use $ewiki_errmsg for <html> strings, or $ewiki_ring for basic access
- granting or invent another variable for later reevaluation by another
- function (your custom ["auth_perm"] plugin for example).
-
-
- $ewiki_plugins["auth_userdb"][] ($username, $password)
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- This is usally called from ewiki_auth_user() which itself got called
- from within an ["auth_query"] plugin (the auth_method_* plugins).
-
- Should return the user 'database' entry for the given user in the form
- array($encodedpassword, $ringlevel, ...) - The returned $encpassword
- is afterwards compared by the ewiki_auth_user() function (usually
- invoked from within auth_query() plugins).
- The array should contain the $ringlevel for the queried user at array
- position [1], but it does not need to be there. Everything afterwards
- that in the array is ignored. So if there are other useful informations
- in your userdb entries, then the ["auth_userdb"] plugin should export
- this itself into $GLOBALS where useful.
-
- Alternatively an "auth_userdb" plugin could compare the $password
- itself or remotely against the contents of its database (and not let
- ewiki_auth_user() do that check). In this case it should fake the above
- behaviour by returning the $password as first entry of an array() in
- the form described above.
-
- The term 'plain auth_userdb plugin' (someties used in this README or
- plugin comments) refers to the more stupid variant that just returns an
- array() entry and lets ewiki_auth_user() compare the unencoded/submitted
- password against the checksum from the _userdb plugin.
-
-
-Examples for your own ewiki_auth plugins
-¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
-
- Your own userdb plugin
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- If you have an existing user database and management system, you'll
- probably like to just reuse that one for ewiki. In this case you just
- needed to write a custom ["auth_userdb"] plugin.
-
- <?php
- define("EWIKI_PROTECTED_MODE", 1);
- define("EWIKI_AUTH_DEFAULT_RING", 3); // read-only for unregistered
- $ewiki_plugins["auth_userdb"][] = "my_userdb";
-
- function my_userdb($user,$pw) {
- $result = mysql_query("SELECT * FROM users
- WHERE user='$user'");
- if ($row = mysql_fetch_array($result)) {
- if ($flags & USERFLAG_ADMIN) {
- $ring = 1; // moderator user
- } else {
- $ring = 2; // ordinary user, may edit/ pages
- }
- return( array($row["password"], $ring) );
- }
- }
- ?>
-
- In this example, we fetched the user data from a MySQL database table
- 'users' with the rows 'name' containing the usernames, 'password'
- containing encrypted or unencrypted (?don't care) password. The 'flags'
- database column also tells wether the fetched user gets moderator
- priviliges (ring 1) or not (ring level 2).
-
- Most SQL user databases are layed out like this one, despite the
- fictional 'flags' column of course. If your database had an 'email'
- field as well, you could add this to reflect it:
- $GLOBALS["ewiki_author"] = $row["email"];
-
-
- Your own perm plugin
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- If you merge ewiki as just one piece into a CMS which already provides
- user authentication, then you could write a complete ["auth_perm"]
- plugin as replacement for ewiki_auth() like this:
-
- <?php
- $ewiki_plugins["auth_perm"][0] = "cms_permissions";
-
- function cms_permissions($id, &$data, $action, $rring, $login) {
-
- $user = & $GLOBALS["logged_in_user"];
- # if (empty($user)) { $user = CMS_Context::get_user_from_cookie(); }
- if (empty($user)) { cms_print_login_form(); }
- $is_admin = & $GLOBALS["user_is_root"];
-
- $actions_allowed = array(
- "DEFAULT" => array("view", "links"),
- "root" => array("edit", "delete", "control", "admin"),
- "user2" => array("edit", "delete", "info"),
- "witch" => array("edit", "comment"),
- "..." => ...
- );
-
- $ok = in_array($action, $actions_allowed[$user])
- || in_array($action, $actions_allowed["DEFAULT"]);
- $ok = $ok || $is_admin;
- if ($is_admin) { $GLOBALS["ewiki_ring"]=0; }
-
- return($ok);
- }
- ?>
-
- Instead of providing global variables your CMS may allow you to fetch
- user state/settings via a function or class API. However this plugin
- shows, how to ignore the $ring level stuff at all (but for the superuser
- you should set it, because admin/ plugins rely on it).
-
-
- No plugin at all
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Here's another example, on how to skip the 'plugin writing' thing
- completely by just setting $ewiki_ring whenever possible (you should
- then load the auth_perm_ring plugin).
-
- <?php
- $ewiki_ring = 3; // view/browse/read-only Wiki
-
- if ($_COOKIE["username"] || $_COOKIE["LOGINSESS"]) { // simple guess
-
- $ewiki_ring = 2; // allows "edit" action and others
-
- if ($user_is_admin) { // (already set somewhere else)
- $ewiki_ring = 0; // this grants access to admin/ plugins
- }
- }
- ?>
-
- This is in fact the recommended way to do restriction stuff (the
- simplest solutions are always the best).
-
-
- Everything into auth_perm
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- As seen above the ["auth_perm"], ["auth_query"] and ["auth_userdb"]
- chains do not need to get implemented completely by your plugin;
- everything could be put altogether into just ["auth_perm"], as it is in
- fact itself responsible for retrieving the username and printing a login
- <form> when required. If you don't have a separate login page you may
- then need to handle even password comparison herin.
-
- And as stated earlier it is the best option to use ["auth_perm"] for
- full customization of access granting, because it completely replaces
- the code of ewiki_auth().
- Because authentication frameworks like phplib intermix <html> output,
- session management, database queries, password checking and permission
- granting into a single API, writing a ["auth_perm"] plugin is often also
- the only possible way to combine them with ewiki.
- Not separating ["auth_perm"] and ["auth_query"] only may have the
- disadvantage, that the login <form> could appear more often than
- necessary. And you should therefore let users login before they browse
- through the Wiki, because phplib and alike are not very $_REQUEST safe.
-
-
-Old notes
-¯¯¯¯¯¯¯¯¯
-When the wiki is in _PROTECTED_MODE, the core ewiki_auth() function is used
-to check if the current user has permission to access the requested function.
-Permission levels are called 'rings', but auth/perm plugins may restrict
-access to functions also based on $action or page $id.
-
-If you just want to restrict your wiki, you will often find it
-easier to write two different wrappers around ewiki. See the
-paragraph in the HowTo section on top of the main README.
-
-The $ewiki_ring scheme is the built-in way to handle all permission
-granting. Use this variable to separate users into the four groups:
-guests (ring 3), ordinary users (ring 2), moderators (ring 1) and
-administrators (ring 0).
-
-While ring permissions fit most usage restriction needs, and are
-the default and built-in way to handle restrictions, they are
-neither important nor required. You could write a customized
-"auth_perm" plugin, which operates on a completely different basis,
-and ignore those "ring levels" at all. With "auth_perm" it is
-possbile to grant permissions much more controlled (finer
-associations), for example by comparing $action and page $id with
-allowed values for any given user.
-
-
-Available auth plugins
-¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
-This is a short overview about the example auth/ plugins that come with
-ewiki. Please note, that all plugin files carry comments on top, which
-often give more detailed informations about how to use them; and you
-may often need to edit some settings inside of them to suit your needs.
-
-The most recommended plugins are currently:
- * auth_method_http
- * auth_perm_ring
- * userdb_userregistry
-but alternatives are always a good thing.
-
-
- auth_method_form
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Provides a login request <form> like it is found in nearly all so-called
- ContentManagementSystems. It stores the retrieved data back into a
- browser Cookie once(!), after it was verified to match the user account.
-
-
- auth_method_http
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Uses the HTTP Basic AUTH method to query users for login informations
- (username and password), whenever it is needed. This is the recommended
- ["auth_query"] plugin; while it cannot be made fancy-looking at all, is
- more professional than the commonly found plain login <forms>.
- (With Mozilla and XUL/XBL coming up, there may well be possibilities for
- beatification of those otherwise boringly gray login dialog boxes.)
-
-
- auth_perm_ring
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Maps ewiki $actions (and also page $id's or combinations) down to the
- four basic ring/permission levels. Edit the config array() inside this
- plugin to change the mapping for existing or new plugin $action methods.
- Almost everybody wants to use this plugin for the _PROTECTED_MODE !
-
-
- auth_perm_unix
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Uses additional per-page UNIX-like "access rights" to map indirectly
- to ring/permission levels of registered users. It does not rely upon,
- but should be used in conjunction to one of the distributed simple
- ["auth_userdb"] plugins. It extends user management by providing user
- groups (which is not a core ewiki_auth feature, and won't become).
-
- The complicated internals are described in this plugins head comment.
-
-
- userdb_array
- ¯¯¯¯¯¯¯¯¯¯¯¯
- Provides the most simple/stupid internal user database - an array of
- usernames and passwords and permission/ring levels. This is useful if
- you only have a small group of active users, because it simplifies
- user management to editing this plugin file (adding users and changing
- passwords or permissions inside its PHP data array).
-
-
- userdb_systempasswd
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Accesses an user database inside of the ewiki database as _SYSTEM page
- "system/passwd". This page/file has a format like the UNIX /etc/passwd
- file; but contrates on usernames, passwords and ring/perm levels. The
- format of this ewiki page/file is described in the plugins comment.
- The _SYSTEM flag of this ewiki page/file requires an administrator user,
- which is the only one allowed to edit the "system/passwd" contents.
-
- To create (or edit) the page 'system/passwd' you will need to enter the
- appropriate URL manually: ".../wiki.php?id=edit/system/passwd", because
- the slash in the pagename makes it somewhat harder to find (ewiki else
- believes the "system/" to be an action parameter).
-
-
- userdb_userregistry
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Provides a ewiki database internal user/password list much like the
- above plugin, but additionally allows user registration and account
- management by non-administrators. The page "system/UserRegistry" then
- contains the user,password,permission data, and can only be edited by
- an ring level 0 user (administrator); while other users can go to the
- virtual page "UserRegistry" to register an account or to change their
- user settings (but of course not their permission level).
- You can easily tweak this plugin to store additional data inside the
- "system/UserRegistry" file for other uses.
-
-
- password_locks
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Is an ["auth_perm"] all-in-one plugin, that allows to attach one
- password to every page, which then locks the page for the user that
- knows it.
-
-
- you.php
- ¯¯¯¯¯¯¯
- Is an ["auth_perm"] all-in-one plugin, that is handy, when you only
- need the superuser/administrator account (like in PhpWiki).
-
-
- auth_phplib
- ¯¯¯¯¯¯¯¯¯¯¯
- Is an all-in-one ewiki_auth() plugin, that uses the 'phplib', which
- itself provides a user management framework and authentication
- functionality (<form> based). It adds permission management customized
- for ewiki. Please refer to this plugins comments, because it allows
- various customizations of course.
-
-
- userdb_anonymous
- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Allows anyone to login using just an email address as password (should
- work with any ["auth_query"] user interface). Automatically grants ring
- level 2 permission, if it detects an address in the HTTP From: header
- field.
-
-
- users_ldap
- ¯¯¯¯¯¯¯¯¯¯
- Tries to login in a LDAP server using the given username and password
- for verification. Just an example for external auth.
-
-
- LiveUser
- ¯¯¯¯¯¯¯¯
- A plugin bundle utilizing the PEAR LiveUser authentication framework
- is separately available in the /plugins/auth-liveuser package, with
- its own README file. It is even much more sophisticated than our
- _perm_unix plugin, and provides user friendly administration pages.
-
-
-
-Terminology
-¯¯¯¯¯¯¯¯¯¯¯
-administrator
- Is a userdb registered user, which has permissions of ring level 0.
- There exist multiple plugins, that are very dangerous to use (database
- admin functions), and should not be accisible to ordinary users or
- guests as well to not damage the Wiki setup or database. Therefore some
- plugins rely on ring level 0 (== superuser level).
-
-editor
- Means an "ordinary user" with ring/permission level 2, which is at least
- allowed to edit/ (and then of course view/) pages.
-
-guest
- An un/registered user in ring permission level 3 (which often is the
- default for EWIKI_AUTH_DEFAULT_RING).
-
-moderator
- A user in ring level 1, which has all permissions of ring 2 and 3, but
- also can execute more dangerous page actions like page delete/ or so.
-
-_PROTECTED_MODE
- this name is in fact used as joke here, the term origins from the
- "virtual protected address mode" introduced in the i386/486 family cpus
- in the late 80s (which is/was the basis for NT/Linux)
-
-ring levels
- are connected to the "protected mode" joke, the 386 cpu also used
- those ring levels (also in the range 0 till 3)
-
-superuser
- Means the same as "administrator" or "root" (these terms in ewiki of
- course do not refer to your computers filesystem).
-
-
-Problems
-¯¯¯¯¯¯¯¯
-ewiki_auth sometimes fails, because it tries to perform authentication first
-when it is actually needed (unlike other systems, where you get annoyed with
-the login <form> before you had the chance to see any page at all).
-
-