Mark Hedges wrote:
[...]
Hi.
Not to discourage you, but to point out some additional aspects..
There is a Belgian proverb that says essentially "one should not try to
be more catholic than the pope".
What I mean by that is that there are many twists to web authentication,
and it is really hard to try and cover all of them at once. Your
intentions are laudable, but you may end up having to chew more than you
intend to. There are some good reasons why the myriad mod_perl
authentication modules only each cover part of the AAA scene.
The underlying truth is that HTTP was designed as a "fire and forget"
protocol, where each request/response cycle is unique and essentially
disconnected from any previous or subsequent request/response.
This means that, whatever you do, you first find yourself fighting
against the fundamental limitations of the protocol. In a way, it is as
if everything you do would be a "patch" applied over an uncooperative
and slippery basic surface. Worse yet, you have to apply your own AAA
patch over the existing patches (such as Keep-Alive, chunked encoding,
NTLM authentication, Cookies, byte ranges, DAV, cgi-bin, proxying..),
and make sure it works with all of them.
For example, if you want to be really agnostic, then you have to start
by saving the whole request each time, no matter if the user is
authenticated/authorised or not, because you do not know this yet. It
is only when the request has started to be parsed, that you know which
of your <Location> or <Directory> sections apply, and thus which
authentication/authorization applies.
There may be clever ways to do this, but I suspect that it might in any
case be very inefficient, and not really workable for a production
environment (the ScriptLog directive of Apache is an example).
You might want to wonder for instance if you cannot instead structure
your application so that, prior to accessing a protected URL, it is not
mandatory to do a first "authentication GET" to some document.
Another avenue may be to apply an old African proverb, which states that
to eat an elephant, one should do it bit by bit.
In other words, specialising your authentication subs by HTTP method,
and apply different schemes to HEAD, GET, POST, PUT, (MKCOL, OPTIONS..).
As an example of twist, imagine the following scenario : a user POSTs
(or PUTs) a very large file to the server. To my knowledge, Apache will
read the POST/PUT entirely and store it somewhere, prior to even calling
your authentication module. Then you read the POST/PUT, save it
somewhere again, and send them a login page to start your authentication
cycle.
Now imagine the user just does not know a valid login, and closes his
browser in despair. How do you clean up ?
As another example, consider the following :
The DAV module/protocol allows one to create "web folders" in one's
Windows Explorer, corresponding on the server side to directories, in
which one can drag-and-drop files directly from one's desktop.
Of course you might want to authenticate/authorise the user doing this.
The Windows Explorer "web folder" implementation however does not
support cookies set by the webserver, so it is hard to do anything based
on cookies, be it only a cookie holding a session-id. It also only
supports Basic (and maybe Digest) authentication (no custom login pages
thus), and it does not support OpenID.
The only way I found was to do Basic authentication, and store the
authentication (or session) data in the Connection structure (like
$r->connection->notes). In that case it fits, because Windows-style
authentication is connection-oriented anyway.
And as long as we are talking Windows (and since at least 90% of
corporations still use IE and Windows authentication internally), what
if one of your customers insists that to authenticate external users,
OpenID is OK, but for internal users they would really like you to use
the integrated Windows authentication (NTLM), since the user is already
authenticated in the Domain anyway.
NTLM authentication would play havoc with your scheme, because it
already itself relies on a multi-step exchange between browser and server.