External Authentication

Introduction &amp; Motivation
Basically, LogicalDOC introduces a common HTTP Authentication mechanism, which lookups user credentials in a proprietary user database. For instance, to login as a user, you´ll type in you username as well as password upon the web interface (or via WebDAV-Authentication Request which being managed through OS). If the user not exist, a system administrator have to be confirmed about this.

Well if a company obtains a central user database(in the most cases a digital directory), of course its a inconvinced issue to make things twice. This means in fact, that the user has to be stored within the directory as well as LogicalDOC if the user have to go for it. The motivation now is for sure, to getting access to the directory and get rid of the overworking tasks.

External Userstores &amp; bridges to the Outworld
As decribed above, companies as well as instituions have in most situations a central managed user store (employees, perhaps partners costumers). LogicalDoc have to be move on, to extend his authentication model in such a case, that connections can be achieved against those directories. The most user directories(in real, those are no user stores than more common directories to store company-wide informations) have a standardised protocol gaining access from a external application. Here comes LDAP in the game, which can be descriped as the SQL-Standard of directories. In the last years LDAP becomes a big player managing users within companies and institutions.

But there are other "user stores" on the market which courts for using. Central Authentication Service manages authentications via HTTP or Shibboleth.

Aims
I think, implement directory access through LDAP is a big hard rock we´ll to claim on the next step - i guess.

Thoughts about it
Well, performance is a very critical mattor for every software-product. LogicalDOC wants to claim the aim to offer best performance to manage millions of documents in a good time/cost relationship. This is not easy, and will be more complicated due to external authentications. For instance, if a user want to list all users of LogicalDOC, the system must made a completely lookup to external directory to retrieve all users. Surely, thats not a good case to make a joke. Nevertheless must we keep an eye on such things. This behaviour could - for example - managed through a cron-job, being executed in a well defined intervall, to retrieve all users from a directory. But here comes the next big issue. Some directories have a query limit. This means, if we wanted to retriev all real users (for real at a count of 1000) we could retrieve an error message from a directories as to many results being expected. This can be manged through set up a much higher rate of resultsets.

Requirements Filled Out
Thoughts about "must haves" obtained by gained expieriences through projects/studies


 * Readaccess against directories =&gt; No Writeaccess is necessary

Description: Main purpose is to read out all available users and hold the line of synchronisation against an external directories.


 * Two main kind of processes are relevant to LogicalDOC: Directly Authorisation and bulk-importing

Description: This means, that we wanted from the one site, to take cover about the current user being logged-in by validating through a directory. On the other site, logicaldoc must posses all currently available users stored in a directory to hold performance on a high level. The regarded requirement is then, to read in a well defined intervall all users from the user store(directory) into logicaldoc (also called: bulk import).


 * Multiple kinds of external authorisation processes can be sticked/combined together

Description: CAS, JAAS are authentication procedures as well. The question here is now: How can we achieve a model of implementation/usage where its easly to install particular system on customers site and implementation efford for developer is not so monstrously(how i think this will be not achieved due to we have not enaugh expieriences with such systems ;-D).


 * ease configuration through external configuration files (e.g. Spring-Context, properties file)

Security Frameworks
As still NOT(will be followed soonly) descriped, some frameworks have the whealthy opportunity that they includes some authentication mechanism which we could take over. For meanings, expieriences would be appreciated.

ACEGI, JSecurity are frameworks to obtain "ad-hoc" credentials to the current user. If we wantet to act as a automatically system, to retrieve data from a directory, those frameworks possesed no way for doing this in an appropriated way. In this time, i recommended the use of Spring LDAP to manage authentication via LDAP.

Rocket Arena &amp; Labour
This is the part of the current document being made for constructive words, questions, processed (mini-)projects and images, too.

Currently im playing with LDAP directly over JNDI as well as ACEGI. ACEGI sounds for me no good idea as we looking in the near future. For clear, Acegi offers ease connections to directory via LDAP. But this involves single query calls when user performes a login. But we need a more better strategy as we wanted to list users to search for those within LogicalDOC. For instance, if we want to list all users within logicaldoc we retrive zero users, as all users being retrieved through ldap. An ldap query takes to long as we can get ad hoc all users. So we have to implement a job, to synchronizing the main userstore with LogicalDOC. This approach must be achieved without A WEBCONTEXT. But Acegi needs such a operation, as Acegie puts his thread to the local Servlet thread.

LDAP Implementation
Based upon current informations wrote down right there, time has been come doing a first test-implementation. Therefore, it should be possible to retrieve all users as well as groups from a directory stored in the end of all in LogicalDOC. LDAP has been prefered as the main protocol as most directories providing LDAP-Support. After a couple of conversations with Marco, we decided following approach:

Authorisation-System consists of two different approaches to manage userdata obtained by directories:


 * At first, all users will be retrived during a cron job
 * Each user will be assigned to at least one group, based upon the ldap data.
 * Every user will be validated against his current login data comparing with ad-hoc user data from directory.
 * Special users can be managed ob implementing an listener interface being invoked on each import/login.

How does mapping user/group working, in detail?

We decide to implement a few approaches for doing this:

1. Static mapping in a configuration depicted like below: &lt;user-mapping&gt; &lt;mapping group="editors"&gt; &lt;user&gt;bbauer&lt;/user&gt; &lt;user&gt;sschmidt&lt;/user&gt; &lt;/mapping&gt; &lt;/user-mapping&gt; 2. Groups can be defined as a query like:

ou=groupName

3. ListenerInterface can be implemented being invoked when a new user will be imported into LogicalDOC.

The Interface could have following decleration: interface LDAPUserEntry { initialise(BeanFactory);

onNewEntry(Principal user, Group groups, Property&lt;String, Object&gt; properties);

};

How will be crons managed?

LogicalDOC uses still cronjobs in the background, so its no matter of decision to use this, of course. An well defined intervall via properties-file leads to a full customizable configuration of job-execution.

Development guide lines

We have to place external authentication in a proper plugin named for example logicaldoc-auth. In this plugin we can place all needed resouces. In addition the LogicalDOC plugin mechanism allows us to add features to the platform such as the new synchronization task.

Which LDAP-Directories will be tested?


 * Windows Server 2003 Enterprise SP2 - Active Directory
 * (Future) OpenLDAP
 * (Future) Apache Directory

How long does it take?

Well, it could be take two weeks, 'til mid of february 09 to gain more practical expieriences with it.

LDAP Cronjob

 * What happens with users being deleted in a directory? -&gt; Which behaviour applies LogicalDOC on the next synchronisation phase?
 * A cron blows userdata and groups from directory into LogicalDOC. What happens with users, being deleted after time?

The more safe way is not to do anything in LogicalDOC. Users are imported only and not deleted. The administrator can delete no more needed users. Another weay is to provide each user with an 'enabled' flag, if the user is deleted into the directory we can mark tje same user as disabled into LogicalDOC.


 * What should happen with reassignment of groups on existing users in LogicalDOC?

Nothing, the administrator can change everithing he wants. It would be useful to provide each user with a flag 'synchronize'. If this flag is true then the user is maintained synchronized with the LDAP entry and all changes applied by the administrator(such as group affiliation) are overwritten.

Important LDAP-Classes
Following classes are excerpted from Apache Directory Studio objectclass ( 2.5.6.4 NAME 'organization' SUP top STRUCTURAL MUST o  MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )

objectclass ( 2.5.6.5 NAME 'organizationalUnit' SUP top STRUCTURAL MUST ou  MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )

objectclass ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn )  MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )

objectclass ( 2.5.6.7 NAME 'organizationalPerson' SUP person STRUCTURAL MAY ( title $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l ) )

objectclass ( 2.5.6.8 NAME 'organizationalRole' SUP top STRUCTURAL MUST cn  MAY ( x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l $ description ) )

LDAP Security
Most directoryservers handle authentication methods crossing each other. For instance, the basic authentication to "bind"(logon) to a Directory server leads to a Simple Bind, where no credentials(password) are encrypted. So a sniffer can catch this password in one catch-around trip. A more sophisticated way to provide a more secure way of authenticating is formaly known "DIGEST-MD5". Over SASL, its possible to obtain a challange response procedure between the client(which is surely a logicaldoc server) and the directoryserver.

LogicalDOC will support both.

But if companies directory spreaded over the world, to achieve a more secure state of authentication, SSL or TSL should be supported.

Active Directory

AD supports mainly two direct authentication methods - Simple as well as DIGEST MD5. Futhermore AD brings two ports on board, where authentication against the user store can be achieved. By default, Port 369 as well as 639 are reserved for those processes.

Here comes the clue: DIGEST-MD5 Authentication via Port 369 works, but no encryption will be done. The secured port is available at 639:

Non-Secured authentication: &lt;bean id="contextSource" class="com.logicaldoc.authentication.ldap.BasicLDAPContextSource" scope="prototype"&gt; &lt;property name="url" value="ldap://adhome:389" /&gt; &lt;property name="base" value="cn=users, dc=localhost" /&gt; &lt;property name="realm" value="localhost"/&gt; &lt;property name="userName" value="swenzky@localhost" /&gt; &lt;property name="password" value="Password1234" /&gt; &lt;/bean&gt; Secured Authentication: &lt;bean id="contextSource" class="com.logicaldoc.authentication.ldap.DigestMD5LdapContextSource" scope="prototype"&gt; &lt;property name="url" value="ldap://adhome:639" /&gt; &lt;property name="base" value="cn=users, dc=localhost" /&gt; &lt;property name="realm" value="localhost"/&gt; &lt;property name="userName" value="swenzky" /&gt; &lt;property name="password" value="Password1234" /&gt; &lt;/bean&gt;

Download document
The implementation details are available in this document logicaldoc-ldap-1.1.pdf