By Peter Bell

What IS Authentication? Are Users the Only thing we should Authenticate?

Authentication is the process of establishing identity. In the context of web based systems, authentication is typically based on one or more tokens (usually two or more) such as a username and password.

A more interesting question is WHAT can be authenticated? I know I can authenticate a site visitor as a user, but what about authenticating them against a company, an order or an article? . . .

Given that companies, orders and articles typically don’t use web browsers (people do), we usually think of authentication as a way of establishing that a person is who they say they are – often by asking them to enter a username and password, but in general by asking them to enter n-tokens, where for any real level of security the minimum value of n is two (just asking someone to enter their email but not a password is a pretty low level of authentication). We then typically associate the site visitor to a User object which has either permissions or (in more sophisticated systems) has roles which determine their permissions.

But there are a number of use cases where you don’t have sufficient information to fully authenticate a user. For instance, if you have placed an order online without creating an account, we know enough about you to authenticate you for access to the order, but not enough to trust you to see all of your historic orders (or even to know for sure what all of your historic orders were). If you have ever been to a shopping site where you entered your billing ZIP plus your order number to check status, you’ve come across this type of system.

Have you ever built a system where you have a company object and all members of a given company automatically have certain permissions? Do you create a separate user table with a 1:1 mapping between companies and users or do you just add a password field to the company table and authenticate the user as a company?

You could look at the first case as a filter rather than authentication (actually most authentication systems are just filters if you think about it – select where UserName = ‘#UserName#’ and password = ‘#Password#’ - remembering to use cfqueryparams to avoid SQL injection). And if you look at the second case, you could just call it a special case. But what about checking a tax return based on a SSN and a submission date? What about being able to manage an article based on its name and its unique editing key? What about checking the status of a form submission based on a submission date, first name and last name? It seems to me that there are a whole class of use cases which could be described in terms of authenticating a site visitor against an object type other than a user.

I am NOT arguing against the benefits of a traditional User:Roles:Permissions system, authenticating users to roles which in turn provide permissions. I am asking whether there is a place for generalizing that solution to provide Object:Roles:Permissions where a tax return could have the permission of viewing itself or a company of viewing all of the products associated to it.

The question is whether there is any value generalizing authentication, providing a system that allows you to define the object type to authenticate a site visitor against (a company, a user, an order, a form submission), the tokens used to authenticate, and any additional authentication properties (maximum number of invalid tries, logging rules, etc.). I created such a generalized system back in my old procedural application generator and I was just looking for opinions. Does a base authenticate method in BaseService for providing these features seem useful or does it seem to be stretching the metaphor beyond breaking?

Any opinions appreciated.

Comments
Peter, I'm a little confused here (forgive me also if this HTML doesn't work out):

<blockquote>
Have you ever built a system where you have a company object and all members of a given company automatically have certain permissions? Do you create a separate user table with a 1:1 mapping between companies and users or do you just add a password field to the company table and authenticate the user as a company?
</blockquote>

Did you mean a separate table with 1:n mapping? Or, is <i>each</i> user also a company? If that is the case, I almost certainly would just add a password field (well, I'd need to be shown a good reason not to do so, rather than a good reason to do it).

But to answer that question, yes we've builde a system where each user from a certain company would have different permissions, but we made it flexible enough to accomodate changes to individual users for a company ... and in fact, now that I think about it, we've recently taken over a project that is doing the same thing.

I like what you said about "actually most authentication systems are just filters if you think about it." This is quite true. In fact, if you view it in that light, I'm not convinced of the "value [in] generalizing authentication." As it stands now, we simply authenticate a user, and then all the subsequent "authentication" (for forms, orders, et al) is done simply with "filters" (say, where userid='#session.uid#'

Now, of course if you don't want to keep user data, I can see the value. But if you are already keeping it, should you harass them some more when they want to see an old form submission? I'm pretty sure that's not what you meant, but that's what I thought about when I read it.
# Posted By Sam | 11/21/06 12:13 PM
Hi Sam,

I meant 1:1. I get that if there are many users per company with different permissions, that's easy. Traditional roles based user security implementation. What I'm asking about is the edge cases where User based security doesn't really fit. Like where there is only one "user" per company (be definition, never to change - ever). Is it really worth creating a whole new table just because your authentication code can only authenticate against user object vs. against any object?

The reason for generalizing authentication is that even though it is implemented via filtering, it is more than filtering. With authentication you may want to log authentication attempts, max out number of invalids per IP and do a bunch of other stuff that would reasonably be encapsulated in either an authentication method or a composed authentication component. The question I am trying to clarify is whether I should allow my base "authenticate" method to be used/called by any object type or only by the user object.

On the one hand I see real utility in being able to solve the edge cases by making authentication something that can be applied to any object type, but I'm trying to get opinion on whether the utility is outweighed by the fact that it is a little bit of a funky concept/approach!
# Posted By Peter Bell | 11/21/06 12:23 PM
Hi Peter,

If I need it, I have objects that implement an Authenticatable interface. It's especially handy for remote APIs where you don't want people to have to pass a user (or token/id, etc.) along to each operation. User and RemoteOperationContext both implement Authenticatable, and therefore the underlying service tier that asks for authentication doesn't know the difference.
# Posted By Joe Rinehart | 11/21/06 1:19 PM
Hi Joe,

Many thanks! From your comment about remote APIs and not having to pass session tokens to each request, does that mean that your authenticatable interface is session aware (isAuthenticated() calls SessionFacade and returns authentication status)? In general, do you see session awareness as a controller function (and controller always passed model some kind of user ID for the model to determine permissions) or as something the model handles?
# Posted By Peter Bell | 11/21/06 1:54 PM
Nope - kind of the opposite.

Things like User and RemoteOperationContext might implement authenticatable, but they're not session-aware. An HTML client may store the current User in session and the Controller tier would be responsible for passing the current user, from session, into the desired operation of the model.

A remote client would pass a RemoteOperationContext (containing authentication credentials) into the remote service (which, in my case, just asks ColdSpring for an instance of the real service and handles any transfer object -> bean marshalling). The remote service would then pass this Authenticatable into the desired operation of the model.

Neither is session-aware: they're just transient beans that implement things like hasRole(). All my service tier then cares about is that for WidgetService.deleteWidget() the expression Authenticatable.hasRole("WidgetManager") is true....doesn't care if it's a user, a remote request, etc.
# Posted By Joe Rinehart | 11/21/06 3:11 PM
Hi Joe,

Many thanks. That helps a bunch. I'm trying to figure out some best practices for security and session management. No doubt I'll be blogging my ramblings as I try to lock down a good generalized approach!

Thanks again!
# Posted By Peter Bell | 11/21/06 5:12 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.