The log of Craig's initial commit for JNDIRealm says:

> TODO:  Support an operational mode where the Realm attempts to bind to the
> directory server using the user's username and password (instead of a
> system administrator username and password).  This is a different enough
> style that it probably should be a separate implementation class.

In the initial commit it is assumed that the user dn can be expressed as a
pattern specified in the server.xml configuration in which the username is
substituted. This is an efficient approach when the assumption is justified,
but quite often it is not:

- users may be held in a tree in the directory (e.g. under different
organizational units)

- the attribute used for naming in distinguished names may not be the same
as that the user enters into the basic authentication dialog box (e.g. the
user might enter mail address as the username rather than uid; the directory
may use commonName in distinguished names rather than uid).

So I suggest we support a mode where the user's dn is found by a directory
search on the value of an arbitrary attribute. This "search then bind"
approach is taken by at least two two other popular applications: pam_ldap
and the auth_ldap module for Apache. Compatibility with the latter means
that people could always use the same directory data for access control to
static pages (via auth_ldap) and to dynamic ones (via Tomcat's JNDIRealm).

Thus there are really two orthogonal options for user authentication

- how the dn for the user is determined (configuration template vs directory
search)
- how the authentication is done (system vs user login)

I think we should support all four variations. Four implementation classes
are a possibility, and would avoid a little run-time overhead, but involves
some code duplication and configuration could be a little awkward to
describe. Another possibility is to implement within the same class, in
which case the processing done by getUserDN() will vary depending upon which
configuration properties are defined. For example, if property
"userDNFormat" is defined, the DN is formed by substituting the username
into a template; otherwise properties such as "userFilter", "userBase" and
"userSubtree" define a search for the DN (as in my original submission).
Similarly if "userPassword" is defined the system login approach is used;
otherwise authentication is done by binding as the user. Either way (or
indeed if we think it'd be better to have two implementation classes with
one option varying within the class) if there's interest I'd be willing to
have a go at it.

On a different but related topic,  I wonder whether it is sensible to assume
that user authentication and the determination of roles always use the same
mechanisms. For example one might want to use a directory service for
authentication but look up roles in a database - or vice versa. Obviously
supporting this would require significant refactoring to the Realm
implementation in general.

Finally I've looked (e.g. in the servlet spec) but can't find a clear
statement about what Principal.getName() should return. The current
implementation returns the username (ie same as getRemoteUser()). Might the
distinguished name be more appropriate when a directory service is used?

John.


Reply via email to