Hi Bruno,
This general idea is good. I have one small objection, though: HTTP
allows multiple challenges per 401 response. This means you might
want to have a guard with parallel authentication checks. For this
reason, I don't think that subclassing Guard per authentication scheme
(basic, digest, etc.) is appropriate.
Rhett
On May 28, 2008, at 4:35 PM, Bruno Harbulot wrote:
Hi all,
Following the discussion on the authentication scheme a few days
ago, I've been looking at
- "Access to connector authentication"
http://restlet.tigris.org/issues/show_bug.cgi?id=503
- "Add notion of realm"
http://restlet.tigris.org/issues/show_bug.cgi?id=504
- "Add support for Guards based password files encrypted by htpasswd"
http://restlet.tigris.org/issues/show_bug.cgi?id=485
I've also been looking a bit more generally at Guards, and this
raised a few questions/observations/suggestions, which I suppose
could be part of this discussion.
I get the impression that a few things in the Guard API are there
for historical reasons (I suppose the first implementation of Guard
only supported HTTP BASIC).
I'm trying to think of a Guard class that would be sufficiently
abstract to model various types of authentication, not only HTTP
BASIC/DIGEST, but also SSL client-certificates, SPNEGO Kerberos,
Shibboleth and perhaps forms.
I'm just not sure that the notions of Realm (i.e. BASIC/DIGEST
realms), Secrets (known Map), SecretResolver, DomainURI and Nonce
all belong there. What I mean is that perhaps there should be
subclasses of Guard per authentication mechanism.
In contrast, the solution suggested to issue 485 (htpasswd) is a
subclass, and perhaps there should be the notion of a authentication-
provider instead. Similarly, I'm not familiar with the OAuth Guard,
but I get the impression it doesn't make much use of Realm, Secrets,
etc.
For example, in Apache Httpd, it's possible to configure
mod_auth_basic [1][2] with several authentication providers used in
to authenticate the user, for example file (htpasswd) or ldap.
There's also a mechanism that In one of the machines I've set up,
I've used something where it's possible to fake the SSL client
certificate as a username in the file. (It's thus possible to have
cert-based authentication and LDAP username/password as a fallback
mechanism.)
There would need to be at least two categories of password-based
providers: the ones from which the secret can be extracted (required
for DIGEST) and the others.
It's just a vague suggestion, but there could be something like this:
* AuthProvider (abstract?)
* SslAuthProvider extends AuthProvider
(checking the subject DN or perhaps other things)
* PasswordAuthProvider extends AuthProvider
(of which the secret itself can't be obtained)
- checkPassword(String username, char[] password): boolean
* ExtractablePasswordAuthProvider extends PasswordAuthProvider
(one that can reveal the secret as well)
- getPassword(String username): char[]
There could be more concrete implementations:
* PasswordMapAuthProvider extends ExtractablePasswordAuthProvider
(more or less the same as the current secret map).
* LdapAuthProvider extends PasswordAuthProvider
(which checks the password against an existing LDAP server)
* HtpasswdAuthProvider extends PasswordAuthProvider
(which checks the password from a file as described in issue 485)
* JdbcAuthProvider extends ExtractablePasswordAuthProvider
(which would get the password from a database)
Then, perhaps a (more) abstract Guard and then classes like these:
* HttpBasicGuard extends Guard
(constructed or somehow provided with a PasswordAuthProvider, it
doesn't actually need to check against a known secret)
* HttpDigestGuard extends Guard
(constructed or somehow provider with an
ExtractablePasswordAuthProvider, since it would need to know the
password)
These Guards could also take a list of providers rather than a
single one, perhaps to have a fallback solution.
All this being said, this wouldn't cover the case I was mentioning
earlier of SSL-cert falling back to HTTP BASIC/LDAP, so I'd need to
think a bit more about this.
In addition, perhaps the AuthProviders could be used in relation to
the Realms, etc. They could provide a suitable instance of Principal
(e.g. LdapPrincipal, KerberosPrincipal, ... when JAAS is used).
There's clearly some overlap between this notion of authentication-
providers (similar to Apache Httpd) and the notion of realms (as in
Tomcat or Jetty).
This would clearly require a bit more thoughts, but does the general
idea seem sensible?
Best wishes,
Bruno.
[1] http://httpd.apache.org/docs/2.2/mod/mod_auth_basic.html
[2] http://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html