Based on discussions prior to and during the Amsterdam conference, we'd like to propose a number of changes to UserDirectoryService/UserDirectoryProvider APIs and implementations. These changes include:
1) Separate user authentication and attribute handling into distinct interfaces – Some institutions only require a UDP implementation for either authentication or attribute handling, but not both and many times these two concerns are handled by distinct technologies, e.g. Kerberos for authN, LDAP for attributes. Mixing the two concerns in the same implementation may be valid in some cases, but they should be still be separated at the interface level to allow for flexible and natural implementation options.
2) Enable clean separation of user authentication IDs, integration IDs and sakai-internal IDs – The ID with which a user authenticates to Sakai or which is provided to Sakai by an external authentication service (e.g. CAS) may or may not be the same as the ID which Sakai should treat as the user's ID for integration with the instituation in general. Also, a user may actually "have" several authentication IDs, each of which should resolve to the same Sakai user account and corresponding integration ID. In general, we're proposing to factor this authentication->integration ID translation capability into the "authentication provider" interface proposed above such that we relieve methods such as UserDirectoryService.getUserByEid() are not left to "guess" at the given ID type.
3) Reduce dependency on getter side-effects in BaseUserDirectoryService – That what look like read methods on UserDirectoryService might actually result in the lazy creation of user account records in the Sakai db may (or may not) be unavoidable, but the internal implementation details could be refined to avoid "surprise" side-effects and improve the overall readability of that code.
4) Relocate UDP implementations out of the providers module and into the user module (with the long-term goal of disolving the provider module altogether) – There may be historical and/or very good reasons why provider implementations are grouped together in a single module, but providers are usually strongly associated with one "top-level" service or another. Locating these implementations as close as possible to their associated top-level service should flatten the learning curve for a new developer as well as simplify dependency graphs in general.
5) Refactor BaseUserEdit out of BaseUserDirectoryService – Implementing default concrete classes as inner classes makes simple extensions thereof overly complex. It's also questionable whether BaseUserDirectoryService should have a dependency on a particular User implementation.
6) Add new interface method: UserDirectoryService.findUserByProperty(String,String) – At some institutions, a user may actually have multiple "integration IDs", as described above. In these cases, we need a generic way to locate users by arbitrary property. This may be implemented as a search against the SAKAI_USER_PROPERTY table or be passed through to an injected UserDirectoryProvider implementation.
7) Introduce new "standard" UserDirectoryProvider and authentication provider implementations, backed by Spring LDAP, capable of invoking pluggable user attribute mapping strategies.
8) Introduce a new "standard" authentication provider backed by Kerberos.
This ticket is intended to act as a starting point for organizing goals at a high-level and creating a corresponding SVN branch. Additional issues will be created to articulate specific proposed changes in more detail.
Discussions on these topics were originally prompted by Ray Davis's work on the following issues:
SAK-9854 - "Allow separation of authentication ID from user's enterprise integration ID in user directory service"
SAK-9983 - "Give DAV-enabled sites a way to cache successful authentications"
SAK-9965 - "Remove unused methods from user directory and authentication APIs"