Page 6 of 20

Posted: Sat May 20, 2006 1:53 pm
by nielsene
As one other possible model to consider:

What if the Authentication Module were more of a code generator/factory:

Code: Select all

$authenticationSource = new DbAuthenticator($connString,$tableName,$usernameCol, $passwordCol,$sessionStorageVar);
// or
$authenticationSource = new DBAuthenticator($dbResource,$tableName,$usernameCol,$passwordCol,$sessionStorageVar); 
// using is_string, etc to behave appropriately

$authRequiredHandler = $authenticationSource->getAuthRequiredHandler();
/* note this would impose a requirement on the application to use the same interface for its handlers as for the handlers written here
* probably either the canHandle/invoke or the execute variety or both
*/

$loginCommand = $authenticationSource->getLoginCommand($usernameSource, $passwordSource);
$logoutComamnd = $authenticationSource->getLogoutCommand();

// application code
$frontControllor->addHandler($authRequiredHandler);

$frontControllor->registerAction("Login",$loginCommand);
$frontController->registerAction("Logout",$logoutCommand);
/* Note that we don't really care how the developer hooks the generated commands/handlers into their application. */

Posted: Sat May 20, 2006 1:53 pm
by Ambush Commander
if its hard to get setup/use it won't receive the usage it deserves.
Oh dear. This is exactly what we're afraid of. Exceedingly important insight, nielsene, let's think about it.

We want this to be:

1. Easy to use
2. Completely configurable

Now, the two aren't mutually exclusive, but they do interfere with each other. First point: don't require any configuration unless it is absolutely necessary. This makes using the thing out of the box as easy as possible.

This has an important implication: if you have a large application, and you decide to plug in the authentication module, we have to assume that the application won't mind that we're directly interfacing with the MySQL database, and they'll switch the module over to their own database access library when they have the time (or motivation). However, bundling ADOdb with the module is completely unacceptable, and any "DB wrapper" class will have to be as minimal as possible.

Now, we start integration with the simplest possible case: a script.php. The user hacked it out real quickly, there's no object oriented programming, they use the mysql_* functions on the database. They also have a primitive authentication mechanism, where a password is hard-coded into the file, and you have to type in the password in order to execute the script. We'll assume that the script takes no other parameters.

It would look like (never mind the sloppy coding):

Code: Select all

<?php

$password = '007neverdies';

if (!$_SESSION['authenticated'] || $_POST['password'] != $password) {
?>
<form action="script.php">
Password <input type="password" name="password" />
<input type="submit" value="Execute" />
</form>
<?php
  exit;
} elseif ($_POST['password'] != $password) {
  $_SESSION['authenticated'] = true;
}

mysql_connect('localhost', 'php', 'default_password', 'data');
mysql_query('UPDATE blah blah blah');
// more stuff.

?>
Ideally, then, the user would want to do this instead:

Code: Select all

<?php

require('includes/authenticate.php');

mysql_connect('localhost', 'php', 'default_password', 'data');
authenticate();

// do priviledged stuff

?>
and the include itself will abort if it's not authenticated, spit out login form, et cetera.

Obviously this isn't complete yet. Will be continued!

The main problem is how much simplification is feasible, and when the time comes that the user decides to build something better, how well it can cope. Nielsene's command generation paradigm sounds quite promising. (has to do a bit of thinking)

Posted: Sat May 20, 2006 2:29 pm
by nielsene
Ambush Commander wrote:The main problem is how much simplification is feasible, and when the time comes that the user decides to build something better, how well it can cope. Nielsene's command generation paradigm sounds quite promising. (has to do a bit of thinking)
Yeah, its a very different model and I have no clue if I like it or not yet for this, but it often helps me to approach a design from a few different angles to see what type of trade-offs are possible.

In terms of viewing the more minimal version of that idea, it could look something like:

Code: Select all

// Configuration and invocation
$authenticationSource = new AdminPasswordRequiredAuthenticator($password,$passwordSource,$sessionStorageVar);
$authenticationSource->authenticate();
I think that the configuration might also need to contain some information required to identify the form that would be generated (ie an action parameter)

authenticate() would be designed as the "Page Controller" version of the module, that basically wraps calls to construct the handlers/commands as needed and create forms/dispatch as needed -- in a sense its a facade over a mini Application Controller.

This would give the needed flex points I think --
we can provide a useful set of builtin Authenticators
-- constants password
-- simple DB backed
-- db backed with attempt counting with various throttling methods, etc
and users could easily extend from here -- for instance if the user wants to extend the simple DB backed one to use their DB abstraction layer.

The other flex point is in how to assemble the primitives -- simple use of the authenticate function, hand-chaining the various generated tools, injection of the generated tools into a more involved front controller.

Finally users who needed would probably find it relatively easy to subclass the Authenticatores to change the effective interface of the generated components if needed.

Posted: Sat May 20, 2006 3:00 pm
by Christopher
There are a couple of converstations going on here.

Authentication - this, to me, means the act of checking credentials against a known datasource. The result of the check is true or false, so we need a call to check that. This is login/logout so we need methods for those. This system needs provide data to the Access Control system so we need a call to get that. So the interface for me is:

Code: Select all

login($credentials) {}
logout();
isAuthenticated() {}
getAccessControlData() {}
Access Control - this, to me, means the act of checking the users Access Control Data against the Access Control Data for the request to see if the user is allowed access. I have being very vague in using the term "Data" here because it could take many forms. I assume it is encapsulated in an object though. So we need to give the Access Control Data from the Authentication System to the Access Control system. We need to provide the Access Control Data for this request. And we need to ask if access is allowed. So the interface for me is:

Code: Select all

setAuthenticationAccessControlData($data) {}
setAccessControlDataForThisRequest($data) {}
hasAccess() {}
I still think that this system should not know anything about forms or front controllers or the like. We can provide adapters to any system and a common implementation, but those are extras.

Posted: Sat May 20, 2006 3:10 pm
by Ambush Commander
Nielsene, I'm still digesting your comment, so just hold on.

Arborint, I have a question. How does your API handle session/cookie injection? Does a session count as a credential, meaning that the user is technically "logging in" every time?

I'm not commenting on access control. I don't have enough experience in the field to really say anything about it. I agree with the idea that these are extras, but they're "essential extras" (if that makes sense).

I googled "Authentication" and came across OSID. Their API standard is:

Code: Select all

interface AuthenticationManager
{
    public function authenticateUser($type);
    public function destroyAuthentication();
    public function destroyAuthenticationForType($type);
    public function getAuthenticationTypes();
    public function getUserID($type);
    public function isUserAuthenticated($type);
}
You can view get the PDFs here (as well as one for authorization): http://okicommunity.mit.edu/filemgmt/viewcat.php?cid=24 . Wikipedia has an article on them: http://en.wikipedia.org/wiki/Authentica ... Definition and http://en.wikipedia.org/wiki/Authorizat ... Definition

Posted: Sat May 20, 2006 3:24 pm
by nielsene
arborint wrote:There are a couple of converstations going on here.

Authentication - this, to me, means the act of checking credentials against a known datasource. The result of the check is true or false, so we need a call to check that. This is login/logout so we need methods for those. This system needs provide data to the Access Control system so we need a call to get that. So the interface for me is:

Code: Select all

login($credentials) {}
logout();
isAuthenticated() {}
getAccessControlData() {}
In general, I agree. However, I thought from the first ~4 pages of the thread that there was a conscious decision to avoid dealing with authorization (and thus access control). Thus if a getAccessControlData() method is provided its practically ensuring that we'll end up with an abstract class as the most implemented component of the toolkit.
Access Control - this, to me, means the act of checking the users Access Control Data against the Access Control Data for the request to see if the user is allowed access. I have being very vague in using the term "Data" here because it could take many forms. I assume it is encapsulated in an object though. So we need to give the Access Control Data from the Authentication System to the Access Control system. We need to provide the Access Control Data for this request. And we need to ask if access is allowed. So the interface for me is:

Code: Select all

setAuthenticationAccessControlData($data) {}
setAccessControlDataForThisRequest($data) {}
hasAccess() {}
not that its a big deal, but I think a cleaner interface would be more along the lines of

Code: Select all

setAccesslControlDataRequired($data); 
allowedAcccess($data); // user "permissions", retrived from the getAccessControlData above
I still think that this system should not know anything about forms or front controllers or the like. We can provide adapters to any system and a common implementation, but those are extras.
I think this depends on if we're building a toolkit, or a plug and play module, etc... If the goal is pushing towards a drop-in module then the system has to take into account the normal insertion patterns. Otherwise its merely a toolkit that developers will need to assemble lots of primitives.

Posted: Sat May 20, 2006 3:39 pm
by Chris Corbyn
// I'm enjoying sitting on-the-fence in this.... you're bringing up some really interesting points (and pitfalls) so I'll be interested to see some strong code start being produced from the discussion here :)

EDIT | I'm almost wondering if this deserves a forum of it's own for something like "PHPDN Community Project of the Year 2006" - we could start a new one each year.

Posted: Sat May 20, 2006 5:10 pm
by Ambush Commander
Overall summary of what we've discussed excluding this last page and some of the page before that. If I missed anything, or I could have organized it better, knock. (I scrapped the other specification)

Code: Select all

Authentication Poll & Community Design [PLEASE JOIN!]
: http://forums.devnetwork.net/viewtopic.php?t=48544

== Poll ==

Unanimous vote for homegrown authentication systems

== Why homegrown? ==

* Lack of trust (Burrito)
* Leanness: only necessary features (Nathaniel)
* Familiarity (Nathaniel)
* Dependencies (Ambush Commander, Hockey)
* Poorly written (Everah)
* Too many options (Hockey)
* Maintenance (Ambush Commander)
* Lack of modularity (Hockey, Everah)
* Extended Beta Period (Ambush Commander)

Instead of using the modules, some people:
* Borrow snippets from others (Hockey, Everah)

== Code by committee (Arborint) ==

* Single person controls code
* Others have voting rights on decisions
* Requirements, use cases, design, unit tests and code
* Ambush Commander leads, Nathaniel, Maugrim_The_Reaper,
  Everah and Arborint as voters

== Authentication versus Authorization ==

* Authentication can be simple (Hockey)
* The two are often clumped together (Hockey)
* Seperate them! (Ambush Commander)

== Customization ==

* Plugins are maintained like core code (Ambush Commander)

== Store What in Session? ==

* Last access, user ID, user name (Ambush Commander)

== PHP 5 or PHP 4==

* PHP 5 allows for more beautiful code (Ambush Commander)
* SPL, interfaces, abstraction, and visibility scope, references. (santosj)

== Audience ==

* Everyone: different layers for different types
* Reusable and packageable (Ambush Commander)

== Interactions (arborint) ==

Adaptors for all of them.

=== Request ===

$_POST and $_GET. Read only, only a few values needed. No direct interaction.

We basically need username, password and remember_me for login. Resuming
a session needs session_id. Remember me needs a token cookie. (Ambush Commander)

Could be generalized into credentials/context.

Authentication_Credentials_Auto is hand written by user to populate variables
from the application wide Context/Request object.

=== Session ===

Read write, associative array or an object.

* Disable query string munging (Ambush Commander)
* Associative arrays are hard to be polymorphic with (Ambush Commander)

=== Database ===

Could be read-only, but usually read-write. Invisible interaction or require
an adaptor?

=== Controller ===
Nebulous.

Pass commands to the controller? (nielsene)

== Features (Ambush Commander) ==

* Challenge/Response login
* Remember Me
** Binding token to IP address
** User clearning of all tokens
** Token limiting to only one
** Authorization-awareness of remember me spawned session
* Password Strength Evaluation
* Assymetrical encryption for password (SSH emulation)
* Login throttling with captchas
* Client based sessions
* Login logging
* Temporary one-use logins/two-factor authentication

== Scope ==

Module, toolkit or patterns book? All three! (Ambush Commander)

Goes from more intrusive to harder to implement.

== Layered Architecture (Arborint) ==

* Acquisition
* Authentication Controller
* Authentication Commands (Ambush Commander)
** Resume session
** Logout
** Login
** Remember me
* Access Control Controller (out of scope)
* Datasource

== HTML Generation for Forms ==

* Simple, unstyled template set (Everah)

== Terminology ==

* Login/logout preferred over Sign-in/sign-out

== Anonymous user representation ==

* user_id = 0 (Everah)
* Uniqueness through sessions/anon tracking (Everah)
** Ambush Commander against it as default: breaks caching and misleading

== Captcha ==

* Don't require it for essential things (Hades)
* Alternatives:
** Audio Captcha (Hades)
** Logic Test (Hades)
** Figlet Captcha (Ambush Commander)
* Generalize to "TuringTest" interface (Ambush Commander)
* Implementation is out of scope (arborint)

== Acceptance and Integration ==

How is the user supposed to use it? External API? (nielsene)

Authentication is a small part of the overall security infrastructure. (nielsene)

Nielsene:
    isValidCredentials (complex)
    isAuthenticated
    getUserName
    logout (destroyAuthenticator)

Posted: Sat May 20, 2006 6:02 pm
by RobertGonzalez
Very nice recap. I think it captured the essence of the discussion so far.

Posted: Sat May 20, 2006 7:21 pm
by Nathaniel
Ah, thank you Commander. :)

I agree with almost all of the points in the recap, but a few I'm not sure about:

Are the features you listed built-in features, or plugins?

If they are built-in features, then I believe the a) login-throttling with captchas, b) the password strength evaluation, and possibly even c) the remember-me feature* should all be plugins. If we have a cool enough plugin system, then adding those would be a breeze. We could even have a "barebones" setup and a "often-used features" setup, when it comes down to distribution.

The fewer built-in features we have, naturally the less code will be in the barebones application, and it will be much easier for developers to digest the ins and outs of the system and quickly adapt it to their needs.

*remember-me is pretty standard, but perhaps in a case where an application didn't need or want it, it would be nice to be able to remove the feature with a simple commenting out of the addPlugin() line.

- Nathaniel

Posted: Sat May 20, 2006 9:06 pm
by santosj
I still don't see how we are going to be interacting with the database. Do we want the user to supply that information and we just
  • create the session (log in)
  • destroy the session (logout)
  • maintain the session
  • session and user security
  • Other plugins mentioned (remember me)
It would be almost impossible to tailor the Authentication to every single predefined database type and table. The issue also is do we assert our own brand of authentication setup? We are only looking for two parameters (correct?) access name and password. The name could also be email or something else. Also, the login form could also want to take three parameters (username, email, password). If we only handled two parameters then the coder would just decide to code their own implementation.

If we only controlled the Session then what is the point? That is the easy part of authentication. I don't see how we can work around not having any configuration (but lets just say I'm not the brightest apple in the orange tree).

Code: Select all

class AuthDbParam
{
	public $handle; // in case they use PDO, ADODB, or a class based database layer
	public $type; // mysql, sqlite, mssql, ... whatever
	public $table;
	public $column;
	public $assert; //username, password

	public function __construct($table, $column, $assert, $type = 'mysql', $handle = false);
}

$usernameCheck = new AuthDbParam('users', 'username', 'username');
$passwordCheck = new AuthDbParam('users', 'pass', 'regex([0-9a-zA-Z])');
or

Code: Select all

class AuthDbAssert
{
	public $results;
	public $username;

	public function __construct($query, $usernameColumn) // Database query, 
	{
		$this->results = $query;
		$this->username = $usernameColumn;
	}
}

$loginCheck = new AuthDbAssert(mysql_query("SELECT username FROM users WHERE username='".$_POST['username']."' AND pass=PASSWORD('".$_POST['password']."')"), 'username');
Part of my requirements would be an ACL to plug into the authentication. So I say that the authentication is done, we should do the ACL. We should also do the Authentication with ACL in mind. I mean, the ACL could be a totally separate component or module. The ACL would already be difficult anyway so anyone implementing it would already have to know a little something something to get it to work. The same is not true with Authentication.

A novice programmer with basic mysql and php skills could easily create it, why should they use our system?
  • Secure (but not all novices care about this... until they are affected)
  • Easy
  • Allows extension
  • Tested
  • Robust
Another issue is how do we handle the different possible encryption that could be in use. They are limited, but they could also be using their own class with their own encryption methods.

Posted: Sat May 20, 2006 9:23 pm
by Charles256
bah..i wish this did have a forum of it's own..it'd be easier to follow :-D Oh well.just thought i'd give a quick clap : claps : cause so far I like what I see. :-D

Posted: Sat May 20, 2006 9:58 pm
by RobertGonzalez
So I just got done shopping at Costco and had a small epiphany. Let me know if I am way off here (right, like you guys wouldn't anyway :wink: )...

At it's most basic form, authentication is the verification of identity. Before anything can be authenticated, something needs to be identified so a match between a given and a known can be established. In our case, we are talking about user authentication. The app will not identify the user. The user will identify himself. The app will take the identity the user supplies and see if that identity matches what the system knows about that identity. A user that does not identify himself would be, well, unknown. A user that chooses to identify himself would, in essence, tell the server that he is now a known person. The server would then process that information and, if the information is authentic, would tell the user that he checks out.

So this leads me to the belief that this app should address user identification which then immediately leads into user authentication. Not to trivialize the process, but something along the lines of...
Server: Hello there, welcome to our site. I am the Server. Who are you?
User: Me? For now, I'm nobody. (The user is unknown)
Server: Very well, since I do not know you I can only offer certain things to you. Please contact me again if there is anything I can do for you.

... time passes ...
User: Ok, I'm ready for more stuff.
Server: Ok, who are you.
User: I'm JoBob.
Server: And do you have your key to get in?
User: Sure, it is Pa$$w0rd.
Server: Hang on a sec, let me make sure this checks out... Thank you JoBob, welcome in.
So at this point, the user is authenticated (or not). What now? Nothing. That's right, nothing. Authentication is done. We're all happy.

But wait, how do we know if this user is allowed to go certain places and do certain things? Simple, add in Authorization and Access Control. Authorization is the system's process by which the authenticated user is either approved or not approved to do certain things. This is not to be confused with being able to go into certain places. This is along the lines of...
User: I want to change the name of this place.
Server: Very well, let me see what you can do... Sorry, but you are not authorized to do that.
User: Well, what am I authorized to do?
Server: Well, let me check... here is a list of things you can do...
Access Control, I would guess, would be the process the system follows to determine whether an authenticated user is allowed into a certain area...
User: I want to go see everyone that is in this place right now.
Server: Very well, let me see if you can go in there... Sorry, but you are not allowed in there.
User: But I'm JoBob. Why can't I go in there?
Server: I know you're JoBob. But only certain people can go there, and according to my records, JoBob is not in the list of allowed people...
So thinking of these processes, I began to think that if we are looking at authentication, we should keep an eye on Authorization and Access Control, but not code authentication around them. In it's essential form, authentication only verifies identity. Nothing more or less. Authentication does not depend on any other developed process. It only depends on information supplied by the user and information known in the system.

Authorization and Access Control, however, depends on authentication. Can we build these into the authentication app? Certainly. But if we are focusing on authentication, we should develop that first and use it's by-products as a featureset of Authorization and Access Control.

And as I run through this thought, session handling is probably not a needed aspect of authentication unless user tracking is a requirement of the app by the end-user (which I am sure some developers would want).

So to recap, my thoughts on this are:
1. Develop Authentication independent of anything else that the app may offer.
2. Develop Authorization (process authentication in essence) as a dependent to Authentication within the scope of this app.
3. Develop Access Control as (location authentication in essence) as a dependent to Authentication within the scope of this app.
4. Develop a barebones session handling wrapper in the event the users of this app want it, but not as a requirement to anything within the app.

Posted: Sat May 20, 2006 10:12 pm
by Christopher
Everah wrote:1. Develop Authentication independent of anything else that the app may offer.

I think this is the first thing we should do and go from there. I described this as checking credentials against a known datasource.
Everah wrote:2. Develop Authorization (process authentication in essence) as a dependent to Authentication within the scope of this app.

I am never sure what Authorization means because it works two ways: you can authorize someone to do something, or you can be authorized to so something. It sounds like an adminstrative action when you grant access to someone for something. I am assuming that this means the rules that are used by the Access Control system so I would roll this into your #3.
Everah wrote:3. Develop Access Control as (location authentication in essence) as a dependent to Authentication within the scope of this app.

I called this a controller because I see this as a only a middle-man that defines conventions and interfaces, and provides some abstract classes.
Everah wrote:4. Develop a barebones session handling wrapper in the event the users of this app want it, but not as a requirement to anything within the app.
I think session handling should be done with a persistence plugin so that it is generalized -- maybe the only one ever used -- but at least it will force us to make the dependencies clear if it is a separate module.

I am seeing the system as several middle-men that make up the framework and modules that are provided by the application (Credential Acquisition, Authorization Rules, Datasource) using the conventions and interfaces we define.

We can provide standard Credential Acquisition (login form, captcha, cookie remember me), Authorization Rules (deny/allow all, is logged in, in group, has permission/role), Datasource (database, LDAP).

Posted: Sat May 20, 2006 10:16 pm
by santosj
Everah wrote:So I just got done shopping at Costco and had a small epiphany.
Most of my solutions or possible solutions come out of scrubbing the floors and dry mopping at work.
Everah wrote:...
I would say that, while it sounds excellent still does not solve the problem that I put forward above.
Everah wrote: So to recap, my thoughts on this are:
1. Develop Authentication independent of anything else that the app may offer.
That is true and is a requirement, but how?
Everah wrote: 2. Develop Authorization (process authentication in essence) as a dependent to Authentication within the scope of this app.
3. Develop Access Control as (location authentication in essence) as a dependent to Authentication within the scope of this app.
I like this as it in turn separates it out even further giving more control to the developer. However it would still have to access the database and no information has been given on how that would be accomplished.
Everah wrote: 4. Develop a barebones session handling wrapper in the event the users of this app want it, but not as a requirement to anything within the app.
If you are going to be doing Session security, then there are a lot more areas than that to consider.