Authentication System

updated as of: March 30, 2015
last author: Andy Theuninck
original author: Andy Theuninck
The latest documentation can be found on the Project Wiki. The information below may be out of date.
The backend eventually needs access controls. In my opinion, the "backendsecurity" column in the employees table isn't going to work. There's enough going on that tiered access just doesn't make sense. For example, the front end manager should be able to edit cashiers but probably not products. Buyers or scanning should be able to edit products but probably not cashiers.

We need something more nuanced (mandatory access controls if you're into terminology). The system described here is included with fannie. It isn't perfect (frankly, the table structure is just bone-headed) but it works and is reasonably flexible.

Authenticating Users

The auth package is primarily SQL based. The UI lets you add and remove users, change passwords, etc. The system can be run entirely this way with usernames and (encrypted) passwords right in the database. Users generally don't like keeping track of lots of passwords, so I've added a couple alternatives.

You can authenticate against an /etc/shadow file. A small utility, shadowread, is included to let apache pull password hashes out without making /etc/shadow readable for all users (PHP-PAM integration was in rough shape when I wrote this). This is just for name & password matching; the user still exists in SQL.

You can authenticate against an LDAP server. I use it with openldap. It could probably be done with Active Directory in a Windows environment. Again this is just for name & password matching.

Both LDAP and shadow logins will automatically create users in the database if needed.


The auth package is structured around the notion of authorization classes. An authorization class is simply something a user is allowed to do - for instance "edit_prices" could be an authorization class.

For finer granularity, there are optional sub-class limits. These are pretty flexible. These don't have to mean the same thing in all contexts, and can be anything that works in a SQL BETWEEN statements. For example, you could use these to give someone permission to edit prices, but only for products in departments 10 through 15. Or you could give someone permission to edit members, but only if their member type is 1.


You can put users in groups and then assign authorization classes to the group. The table structure for this is idiotic but functional. It saves some headaches rolling out a new tool or trying to remember all the authorizations a new employee needs.

Tying it all together

There are really only two functions that get used a lot to access user information from Fannie: The login page (auth/ui/loginform.php) accepts an optional GET argument in the URL, redirect. So a fannie tool that uses authentication will have a little section like this:
if (!validateUserQuiet("edit_prices")){
	$redirect = $FANNIE_URL."item/itemMaint.php";
	$loginpage = $FANNIE_URL."auth/ui/loginform.php";
	header("Location: $loginpage?redirect=$redirect");
This sends the user to a login form, if needed, and once they enter a valid username and password brings them right back to what they were doing.


10Nov12 EL This procedure may have been superseded by the above:
The auth packages uses itself to check who can edit users, permissions, etc so there's a little backdoor for initial installation.
  1. Create a file in auth/ named init.php. It can be empty.
  2. Go to auth/ui/menu.php in a browser.
  3. Create a user for yourself. Remember your password.
  4. Give your user the authorization "admin". This provides access to manage the auth package.
  5. Delete the init.php file created in step one.

Drawbacks and/or Gotchas

Just stuff to be aware of. Some can probably be fixed, some are inherent.