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.
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);
}
?>