Page 4 of 20

Posted: Thu May 18, 2006 10:36 pm
by Christopher
Extra tools we want:

challenge response - I don't think we care about the challenge, only the response.

remember me - plugin
password strength evaluation - add on
password assymetrical encryption - outside scope?
captchas - outside scope
Ambush Commander wrote:This project might be a little too big for a little forum thread. SourceForge, anyone?
Let's see if we get anything reasonable first.

Posted: Fri May 19, 2006 3:32 am
by Maugrim_The_Reaper
I would stick with the core functionality and worry about extras later. Maybe add some structure for imposing additional filters assuming that would work. I also agree with Aborint - no direct interaction with the request. Adding that is going to impact on whatever is locally being used to package and filter it from $_POST.

Will have more once I escape overtime at work...if.

Posted: Fri May 19, 2006 11:02 am
by RobertGonzalez
I'll tell you what, with the scope of this thing growing at the rate it is, and the functionality that is proposed coupled with the modularity that is being spelled out, this thing looks to be like a killer app. I would say that if the first draft codebase amounts to something that is workable, it might be best to make this a project instead of a thread.

So far this thing sounds sweet.

Posted: Fri May 19, 2006 2:46 pm
by Christopher
Ok, where are we? Maybe we should start with one type of authentication (straight username/password) ... talk through the design ... make some decisions ... and create a scratch implementation. Then try a different type of authentication, repeat and see what's the same and what different.

Posted: Fri May 19, 2006 2:52 pm
by Ambush Commander
password assymetrical encryption - outside scope?
captchas - outside scope
I agree that implementing a captcha is outside our scope, however, creating an interface for them is definitely a major part. If we have three attempted logins, we should throttle the user by forcing them to also fill in a captcha.

The assymetrical encryption is a closer to SSL challenge/response emulation. The way it would work is with the JavaScript library linked we send the user the server's public key when they log on (perhaps also with a challenge or unique ID). The user then fills in the form, the JavaScript asymmetrically encrypts it before sending it the server. Since the server has the private key, it is the only one who can decrypt it, and then rehash it to compare with the database. This benefits over the fact that rehashing the password in the hashed challenge/response greatly diminishes the number of hashes. And besides that it's a kick-ass feature. :lol:

You're right though, we should focus on the core.
challenge response - I don't think we care about the challenge, only the response.
I disagree: we should have a maintained fixture that issues challenges in order for the user to formulate their own from or, if possible, to use.

The three basic items from a login request we need are the username, the password and the remember me. Depending on whether or not challenge/response is being used, there might be extra fields, but we can probably squeeze it all in "password".

Code: Select all

function login($user, $password_data, $remember_me);
When authenticating from a cookie/session, we would need to access the cookie to find the session name (done transparently by PHP's session management but always a good thing to keep in mind), and the $_SESSION array to grab the authentication info (which could be simply one item in the array, a serialized object (CLOB) or multiple items. Besides whether or not a user is authenticated, the session should also contain information on whether or not the session has expired/the last time the user accessed the website.

Code: Select all

// this is barebones, there's probably more stuff needed
function resumeSession($authenticated_user_id, $expiration);
I think we should outright disable GET session data passing. For anonymous visitors, sessions should not be essential, and if they are, you probably should get the user to allow cookies (if they're blocking them to begin with). Munging URL strings is just incredibly ugly, and, for some reason, DevNetwork/phpBB always seems to think I need it to be passed via GET (I am accepting cookies, hello!)

Another possibility is completely client based sessions. You encrypt the data and send it to the client to respond (I got the idea from Schnossagle's book Advanced PHP Programming). Personally, I'm not so crazy about the idea, but it's a possibility.

Authenticating from remember me is an interesting problem. The way I managed it last time was had a database table called "tokens". Whenever a user logged on with remember me, I would issue them a new token and put it in the database. When a user attempts to access a page and doesn't have a valid session (none or an expired one), I then make sure the remember me token they transmitted exists in the database, and, if it does, I would initialize a valid session for them. I liked that method a lot. However, there were three features I didn't implement: 1. binding the token to the IP address from which it was issued, 2. allowing the user to clear all of their tokens from the database and 3. allowing user to only allow one valid remember me token at a time. Also, when it comes to authorization, the application needs to know whether or not the valid session came from a direct log in or a remember me.

Another feature (I've been thinking about this for a long time, doesn't need to get implemented at the start, of course, but we should design with it in mind): temporary one-use logins. User expects to need to login from an untrusted machine. They have the software generate several random passwords for them and they print it out. Then, they use them one by one for each session they need. After one use, the password is no longer valid. They also have a panic code which clears all the temporary passwords without needing them to log in.
Maybe we should start with one type of authentication (straight username/password) ... talk through the design ... make some decisions ... and create a scratch implementation. Then try a different type of authentication, repeat and see what's the same and what different.
So... should I write a naive simple authentication or try to incorporate as many design extras to facilitate adding future features?

Scope - remember, this is supposed to be a toolkit. So there's many different "tools" we present to the potential user to use. The application must be able to work fine without any of them, but must integrate gracefully with all of them.

Another problem - how do we have the authentication change application flow (like redirect to the login page, etc)? Exceptions?

More comments:
Session - This need to be read/write access to some data structure because we have a number of values to store. A plain-old associative array may be easiest. If it an object then the external session system need to know about the class which is just one extra thing to do. When the allows multiple autoloaders this will be easier.
Well, the problem with a plain-old associative array is that it's difficult to be polymorphic with them. If we have an object (a polymorphic one to boot), we'll be able to have it handle saving itself to the session array ($_SESSION = $this; in __destruct()). There's no doubt that the class WILL be interacting with session data, so we should have an interface for it (that's another thing I dislike about associative arrays).

Bare bones interfaces

Code: Select all

<?php

interface AuthTools_Interface_DBGateway
{
    public function getUserPassword($user_handle);
}

interface AuthTools_Interface_SessionGateway
{
    public function setAuthenticatedUser($user_id);
}

?>

Posted: Fri May 19, 2006 4:19 pm
by Christopher
It seems to me like this shaping into a MVC system of sorts -- not actually MVC but layerd like that. There seem to be three distinct systems:

- An Acquisition system that is the interfaces to some source of credentials. The most common for us would be getting username/password from a sign-in form and getting a generated key from a Cookie. Those would be separate acquisition modules that would provide credentials via a standard interface.

- An Authentication Controller that manages the authentication process and that provides some standard interfaces for controller code in the application to access/provide.

- An Access Control Controller that is lean enough to be included every request. It makes the to grant access based on the current data, or force authentication of no data or some other criterion is met.

- A Datasource that the controller gives credentials to and it then provides the controller with data to use for Access Control.

The Authentication Controller and the Access Control Controller would be the core of the system, although there may be some variants of those. The Acquisition and Datasource parts would be external to the system. We could provide some standard ones (e.g. sign-in form, get cookie, Database datasource, HTTP Auth, LDAP, etc.), and provide an Adaptor interface for systems to plug into the controllers.

Posted: Fri May 19, 2006 5:11 pm
by Ambush Commander
I think a specification would be more useful than code at this point. I'm currently drawing one up.

Posted: Fri May 19, 2006 5:32 pm
by RobertGonzalez
Ambush Commander wrote:I think a specification would be more useful than code at this point. I'm currently drawing one up.
I think this is a heck of an idea. It makes sense to know what process you are coding for to make the code development process more specific and focused.

Posted: Fri May 19, 2006 6:21 pm
by Gambler
Access control is tricky. Different systems have different "units" user can call. For example:
?Articles.show.21
/nodes/8734/show
/reviews/21?forPrint=y
Etc.

IMO, if you want to create something versalite, login management, access control and session management should be completely independent.

Posted: Fri May 19, 2006 6:23 pm
by Ambush Commander
Gambler wrote:Access control is tricky. Different systems have different "units" user can call. For example:
?Articles.show.21
/nodes/8734/show
/reviews/21?forPrint=y
Etc.
Ehh... I thought we weren't worrying about access control for now...

Posted: Fri May 19, 2006 6:37 pm
by RobertGonzalez
I think it makes sense to work on this programmatically. Identify the need we are meeting, identify the target audience, code to an identified specification. I think the need and the audience are already identified. The next step is to identify a spec and develop according to it. That is sort of what has been done in the thread so far, though AC is drawing up a spec as we speak (erm..., post).

Posted: Fri May 19, 2006 6:54 pm
by Christopher
Gambler wrote:IMO, if you want to create something versalite, login management, access control and session management should be completely independent.
I don't this will actually be a problem because the application will probably supply both ends of the system -- so the app supplies the interpretation of the data it provides.

When Everah says "heck" I think it is specification time. ;) We should probably start with the most basic requirements and a general module breakdown. Do the modules I listed above make sense?

Posted: Fri May 19, 2006 9:07 pm
by Ambush Commander
I hope no one objects to the spec being written in TeX.
When Everah says "heck" I think it is specification time. Wink We should probably start with the most basic requirements and a general module breakdown. Do the modules I listed above make sense?
They do make sense. The Authentication Controller, to extend the pattern further, handles several commands: Login, Logout, Resume Session and Resume Session from Remember Me.

I also realized that generating the HTML forms for login systems is quite an involved process (this is from experience mates). Though we shouldn't overextend ourselves, we should probably give a prepackaged solution.

Posted: Fri May 19, 2006 9:52 pm
by RobertGonzalez
The HTML should be simple enough. Since the objective is to develop a usable, portable application, there should be the most minor emphasis on design. I think a simple, unstyled HTML set would be adequate since most folks that use the app will probably tailor it to their needs anyway.

Posted: Fri May 19, 2006 10:00 pm
by Ambush Commander
Argh... I just realized that a controller needs a $context object. If we pass each parameter individually, it looks something like...

Code: Select all

class AuthTools_Controller
{
    public function getCommand($login, $login_id,
        $login_pass, $login_remember, $logout,
        $remember, $session) {
        
        // test parameters to determine appropriate action
    }
}
Do we need a parameter object?

Current revision of the specification.

Code: Select all

\documentclass{article}

\usepackage{hyperref}

\title { AuthTools \\
         \small{\textsf{a new way of looking at authentication}}
       }
\author{Edward Z. Yang \small{\texttt{edwardzyang AT thewritingpot DOT com}}}

\begin{document}

\maketitle

Several users of the \href{http://forums.devnetwork.net/index.php}{DevNetwork}
forum were quite suprised to discover that
the majority of authentication systems out there are home-grown. In fact,
the vote was unanimous. In the ensuing discussion, we realized that most
of the authentication packages out there had several deficiencies and also
had very rigid architectures, making it difficult to adapt them to the
appropriate environment. AuthTools looks to give users a set of tools for
authentication that range from the basic framework to goodies like assymetrical
password encryption and response/challenge functionality.  

\section{Current Packages}

This is just a list of the current authentication packages out there.

\begin{itemize}
    \item PEAR::Auth
    \item PEAR::LiveUser
\end{itemize}

\section{Traps to Avoid}

Why fix something when it isn't broken? Well, one could argue that the current
third-party authentication systems are broken. Here are some complaints against
some of the current packages out there:

\begin{itemize}
    \item PHP 4 compatibility%
        \footnote{Admittedly, it can be a mixed blessing. We decided,
        however, that we were trying to build something beautiful over
        something that would work with most shared hosts out there.}
    \item Callback function to display form (PEAR::Auth)
    \item Excessive dependencies (PEAR libraries)
    \item Incomplete (the Extended Beta Phase Syndrome)
    \newpage % FRAGILE: the below bullet is too close to footnotes
    \item Inflexible
    \item Functionality overlap
    \item Inability to adapt code to alternative database schema
    \item Mixing authentication with authorization
\end{itemize}

\section{Simplified Use Case}

This section describes a basic use case for a standard authentication system.

An anonymous user, Alice%
    \footnote{For more information on the choice of name, see Wikipedia's
        excellent article \emph{Alice and Bob} at
        \texttt{http://en.wikipedia.org/wiki/Alice\_and\_Bob}}%
, has hit a site. The site (wisely) refrains from
starting a session, and Alice surfs around and reads a few articles. The
authentication system tells the rest of the application that an anonymous
user is surfing (perhaps by setting her \verb|user_id| to 0).%
    \footnote{Note that what the rest of the system actually does with this
    information is actually access control and is not actually part of the
    ``authentication'' problem.}

Now, it turns out that Alice had actually registered an account on the server.
When she's anonymous, the authentication system has no clue that it's actually
Alice surfing. Sure, it could try comparing his IP address with a database of
known users, but there's no way to tell whether or not it's Alice and not her
evil nemesis coworker Oscar who is on the same network (and has the same IP).
Alternatively, Alice could be one of the poor souls who is
stuck with AOL web access and thus a dynamic IP address.

So, when Alice goes to log in, Alice would like to prove to the server that
she is Alice and not Oscar. In the web world, passwords have become the
standard method of identification. Alice navigates to the login page and
types in her username and password. She clicks submit.

The server receives the request as usual, but this time, when the authentication
controller is called, the controller realizes that because
\verb|$_POST['login']| is set, it should attempt to log the user in. So
the module hooks up with the data source (database, LDAP, etc.), grabs
the password data for that user, and does whatever mumbo jumbo it does in order
to figure out whether or not the password the user has given is valid (usually
hashing the supplied password with the salt and comparing it to the value in
the database). It discovers, ``Why yes! This is Alice! Let's tell everyone
else.'' It creates a session for Alice (stashing Alice's user ID, name and
some other essential data), which the authorization module will interface with
to determine whether or not Alice has the rights to perform a certain action.

In order to make sure Alice can present the server with a ticket for the created
session, the server sends back a cookie containing a session number. Now, on
each subsequent request, Alice's browser will send the cookie to automatically.
The authentication controller, noting that neither \verb|$_POST['login']| nor
\verb|$_POST['logout']| is set, now turns to the session cookie and makes
sure the session Alice claims is hers is valid (for it could be nonexistent,
or have expired).

Alice, being the security-conscious person she is, has finished browsing as
a user and now signs off. Had she not signed off, the browser would have
destroyed the session cookie when it closed, and the session itself on the
server would eventually expire. But she has signed off, and the authentication
controller knows that it should explicitly destroy the session. Alice's
session is now over.

While the above use case omits such features as remember me, login throttling
or challenge/response authentication, it demonstrates that at its very heart,
the core authentication module is a controller. It can either read the
environment or be passed all the environmental variables it needs:

\begin{verbatim}
class AuthTools_Controller
{
    public function getCommand($login, $login_id,
        $login_pass, $login_remember, $logout,
        $remember, $session) {
        
        // test parameters to determine appropriate action
    }
}
\end{verbatim}

\end{document}