LDAP Authentication

LDAP (Lightweight Directory Access Protocol) is a widely used open directory services protocol, which allows computer systems to access user directory information over a network. LDAP provides a way to organize information (often user authentication information) in a hierarchical manner. It’s been around for decades and is implemented by OpenLDAP and Active Directory.

SeedDMS has support for LDAP from it’s very beginning, but quite to often it is difficult to set up. The reasons are manifold due to the many options when setting up an LDAP server.

The way LDAP is integrated into SeedDMS

SeedDMS basically used LDAP for authentication and did not read any information for take over into the user’s profile. That’s not quite true anymore, but let’s just focus on authentication for now.

When a user logs into SeedDMS he/she is first authenticated against the internal database. If that fails, further authentications will be tried and one of them is LDAP if it is configured (see below).

An LDAP server stores a hierarchical directory, often starting with the top level domain, followed by the domain, departments, organizational units, etc. All levels are concatenated with a ‘,’ to form a string ordered from lowest to highest level, e.g. ou=research,dc=seeddms,dc=org or ou=users,dc=seeddms,dc=org. The organizational unit users groups all users into one level and each user can than be identified by e.g. uid=admin,ou=users,dc=seeddms,dc=org. The whole string is called a distinguished name because it uniquely identifies an entry in the LDAP hierarchy. The part dc=seeddms,dc=org or ou=research,dc=seeddms,dc=org is called the base of a distinguished name (baseDN).

If a user wants to authenticate against the LDAP server he/she must provide the full path e.g. uid=admin,ou=users,dc=seeddms,dc=org (called bindDN) and a password and than bind to the server. If that succeeds the user is authenticated. Well, in real life things are a bit more complicated, mostly because LDAP servers behave differently and it is often difficult to predict the correct bind DN for a user.

SeedDMS executes the following steps when a user submits the login form (skipping the database authentication which always comes first).

  1. Connects to the LDAP server
  2. Does a first bind, either anonymously or with the bind DN and password of a user with sufficient access rights to search for users (must be configured in the settings)
  3. Searches for the user trying to login (optionally with a filter)
  4. If a user was found, takes its DN and does a second bind with that DN and the password provided by the user.
  5. If that last bind succeeds, the user will be authenticated

The search in step 3 searches relative to the base DN and finds users with the username entered in the login form. Depending on the type of server (AD or ldap) it uses either the field sAMAccountName or the uid field to identify a user. The filter in step 3. could be used to allow only those users to log in that match a filter criteria, e.g. having a mail address ((mail=*)). Keep in mind, that this filter is not a complete LDAP filter, because SeedDMS already sets it to &(uid=username) (or &(sAMAccountName=username)). Your configured filter will be added at the end, e.g. &(uid=username)(mail=*).

The above procedure assumes the user intending to log in to be already present in SeedDMS. However, this may not always be the case or even not possible if there are many users in your LDAP directory, with new users being added and old ones being deleted over time. For that case SeedDMS can take over the user data from the LDAP directory following successful authentication.

Configure LDAP authentication

The LDAP configuration in SeedDMS is not available through the web gui. You will need to open the settings.xml file with your favorite text editor and search for connectors. That xml tag has one or more child elements called connector. There are usually two connectors partly preconfigured but disabled. One for a regular LDAP server and one for an Active Directory server. Enable one of them them, adjust the host and port and set baseDN. host can be either a standard hostname or an LDAP URI, that includes the protocol, the host and optionally the port, e.g. ldap://localhost:389. In case of an URI the port in the configuration must remain empty.

In rare cases (if anonymous binds are allowed) this could be sufficient but usually you need to set the bindDN and bindPw to specify a user which is allowed to search for users. Without setting a filter that search will be solely based on uid=username. If filter is set to e.g. (mail=*) the query will become &(uid=username)(mail=*)) which will find only users with an email address.

The last attribute groupField (available since 5.1.32 or 6.0.25) tells SeedDMS which LDAP field holds the distinguished names of groups the user belongs to. This setting only takes effect if the attribute restricted in the xml element authentication is set. In that case the group membership of the user will be imported into SeedDMS.

Take over data from LDAP

SeedDMS has a configuration parameter called ‘Restricted access’. If that is set to false (or not set) then a none exiting, but successfully authenticated user, will be added to the user database and an already existing user will be updated. The data taken from LDAP only includes the full name and email (and of course the user name if a new user is created). The password will never be set, because the user would be able to log in the next time without authenticating against LDAP, because database authentication always comes first. So why not disable database authentication if LDAP authentication is on? That would not allow local users (like an admin account) to log in even if the LDAP server is not available (see below for precedence of authentication).

Version 6.0.25 of SeedDMS even goes a step further. It can also take over group membership of users. It is turned on by setting the attribute groupField in SeedDMS’ LDAP configuration to the name of the LDAP field storing the groups of a user (usually memberOf or memberof). This LDAP field must contain a list of distinguished group names, e.g. cn=marketing,ou=groups,dc=seeddms,dc=org. SeedDMS will take the cn of each group, checks if that group already exists in SeedDMS, creates it if not, and adds the user to that group. If a users does not belong to a group anymore that user will loose its membership.

Precedence of authentication

As mentioned above, database authentication always comes before LDAP authentication. Hence, if database authentication succeeds, LDAP authentication will not even be tried. The allows local SeedDMS admins who can always log in. On the other hand, if database authentication fails (because the password in the database is not set or the user misspelled the password) then LDAP authentication will be tried. In a theoretical case, there could a local SeedDMS user and a LDAP user with the same user name but different passwords. If you intend to log in as the local user but happen to enter the LDAP user’s password, you’ll be authenticated. So far no problem, but if data from LDAP is synced into your SeedDMS database it may mess up your local user. Just keep that in mind.

As you may have realized, there is no distinct flag to turn on LDAP or database authentication for a user. If a user must be authenticated by LDAP just clear the database password or set it to some unguessable value and turn off the ability in SeedDMS to change its own password (a config option available since 5.1.32 and 6.0.25)

Alternative LDAP server

LDAP servers are usually run by medium to large enterprises with lots of users. There is no advantage of running it for small companies or even on your private server, because of the administrative burden. But, if the LDAP server needs little attention and uses an already existing user base it becomes a viable option. directoryd (https://ezix.org/src/pkg/directoryd) is such a LDAP server serving locally defined users and groups from /etc/passwd and /etc/group. Once configured it needs little to no attention and also includes a web interface to change the user’s password.