In the Nuxeo Platform, users and groups are managed by directories. If you want your Nuxeo instance to use a LDAP directory you will need to:
- configure a user directory pointing to your LDAP server(s),
- configure a group directory pointing to your LDAP server(s) (if you need LDAP groups).
Of course you can have a specific custom config where:
- you use a custom user / group schema,
- you use several LDAP directories, or a mix of SQL and LDAP directories.
But for the most common use case, all you want to do is map the default userDirectory
to your LDAP Server. Since groups are used in Nuxeo to associate permissions with content, fetching groups from LDAP is usually not very efficient: LDAP groups are usually not designed for that.
Configuration
You can find a full example of contribution to the userManager extension point on the explorer. Here is a review of the specific useful parts.
Users are defined on the users
element:
<userManager>
<users>
<directory>somedirectory</directory> ...
The value somedirectory
is the name of a contributed directory (see LDAP and SQL users contributions, as well as multidirectory).
Groups are defined on the groups
element (also referencing already contributed directory).
<groups>
<directory>somegroupdir</directory>
<membersField>members</membersField>
<subGroupsField>subgroups</subGroupsField>
<parentGroupsField>parentgroup</parentGroupsField>
<listingMode>search_only</listingMode>
</groups>
Default Users and Groups Configuration
By default, the platform's administrator is the principal "Administrator". On the same contribution to the UserManager extension point you can define which principal from the remote identity provider will be the administrator of the application, instead of Administrator. That way you can assign a "real" user. This is done using the defaultAdministratorId
element.
You can also choose a group from your company's directory instead of using the default "administrators" group, to determine the users who will benefit from all the rights in the platform. This is done using the administratorsGroup
element.
There are 2 ways to define your LDAP configuration:
- Set all out-of-the-box LDAP variables in
nuxeo.conf
- Providing an XML contribution for your LDAP configuration
The first approach allows you to simply reuse the default LDAP configuration template here by providing values for each variable defined in this template. The advantage of that solution is you don't have to deal with future upgrades config changes as you simply define variables in nuxeo.conf
. If changes are required then the template will be automatically updated at the future upgrades.
If you need to add other custom setting where the template doesn't define any variable for that config then the second option would be better. You will have to maintain this contribution for future Nuxeo upgrades.
LDAP Configuration Variables (nuxeo.conf)
To enable LDAP authentication, add the following properties to your nuxeo.conf
file. Default settings are shown with bold italics, while example settings are shown with monotype
.
Connection Parameters
Property | Values | Description |
---|---|---|
nuxeo.directory.type | default, multi, ldap | Select where Users and Groups are managed
|
nuxeo.ldap.url | ldaps://ldap.example.com |
LDAP URL |
nuxeo.ldap.binddn | cn=nuxeoldap,dc=example,dc=com |
Bind DN provided by your LDAP administrator |
nuxeo.ldap.bindpassword | secret value |
Bind Password provided by your LDAP administrator |
nuxeo.ldap.retries | 5 | Number of times to retry query |
nuxeo.ldap.query.sizeLimit | 200 | Maximum number of entries to return per query |
nuxeo.ldap.query.timeLimit | 0 | Query timeout in milliseconds (0 means no timeout) |
Default Mapping
Property | Values | Description |
---|---|---|
nuxeo.ldap.defaultAdministratorId | johndoe |
Trusted user that is assigned Administrative privileges |
nuxeo.ldap.defaultMembersGroup | members | Nuxeo Group assigned to properly authenticated LDAP users |
User Search Parameter
Property | Values | Description |
---|---|---|
nuxeo.ldap.user.searchBaseDn | o=users,dc=example,dc=com |
Base User DN provided by your LDAP administrator |
nuxeo.ldap.user.searchClass | person | Search class used to locate Users within the directory |
nuxeo.ldap.user.searchScope | onelevel, subtree, object | Search scope used to locate Users within the directory
|
nuxeo.ldap.user.searchBehavior | subany, subinitial, subfinal | Specify how partial user identifiers are matched against directory entries
|
nuxeo.ldap.user.readonly | true, false | Enable or disable modification of User details from Nuxeo - requires authorized bind DN |
User Mapping Parameters
Property | Values | Description |
---|---|---|
nuxeo.ldap.user.mapping.rdn | cn OR uid |
Relative distinguished name for the LDAP user |
nuxeo.ldap.user.mapping.username | cn OR uid |
Base User DN provided by your LDAP administrator |
nuxeo.ldap.user.mapping.password | userPassword |
LDAP attribute containing the user's credentials |
nuxeo.ldap.user.mapping.firstname | givenName |
LDAP attribute containing the user's first name |
nuxeo.ldap.user.mapping.lastname | sn |
LDAP attribute containing the user's last name |
nuxeo.ldap.user.mapping.company | ou |
LDAP attribute containing the user's company (optional) |
nuxeo.ldap.user.mapping.email | mail |
LDAP attribute containing the user's email address |
Group Search Parameters
Property | Values | Description |
---|---|---|
nuxeo.user.group.storage | default, userLdapOnly, multiUserGroup, multiUserSqlGroup, ldapUserMultiGroup | Select how Groups are added to a User within Nuxeo
|
nuxeo.ldap.group.searchBaseDn | o=groups,dc=example,dc=com |
Base Group DN provided by your LDAP administrator |
nuxeo.ldap.group.searchFilter | (|(objectClass=groupOfUniqueNames)(objectClass=groupOfURLs)) | Search filter used to return Group entries from the LDAP server |
nuxeo.ldap.group.searchScope | onelevel, subtree, object | Search scope used to locate Groups within the directory
|
nuxeo.ldap.group.readonly | true, false | Enable or disable modification of Group details from Nuxeo - requires authorized bind DN |
Group Mapping Parameters
Property | Values | Description |
---|---|---|
nuxeo.ldap.group.mapping.rdn | cn |
Relative distinguished name for LDAP groups |
nuxeo.ldap.group.mapping.name | cn |
LDAP attribute containing the group name |
nuxeo.ldap.group.mapping.label | description |
LDAP attribute continaing the group display label |
nuxeo.ldap.group.mapping.members.staticAttributeId | uniqueMember | LDAP attribute containing the static group members |
nuxeo.ldap.group.mapping.members.dynamicAttributeId | memberURL | LDAP attribute containing the query for the dynamic group members |
Emergency User
The Emergency Administrator may be selectively enabled to provide access to the Nuxeo Server when other forms of authentication are not available.
Property | Values | Description |
---|---|---|
nuxeo.user.emergency.enable | false, true | Enable or disable the emergency user |
nuxeo.user.emergency.username | MyAdministrator | Emergency administrator username |
nuxeo.user.emergency.password | secret value |
Password for emergency administrator |
nuxeo.user.emergency.firstname | Emergency |
Emergency administrator first name |
nuxeo.user.emergency.lastname | Administrator |
Emergency administrator last name |
Default nuxeo.conf
Configuration Example
nuxeo.directory.type=ldap
nuxeo.ldap.url=
nuxeo.ldap.binddn=
nuxeo.ldap.bindpassword=
nuxeo.ldap.retries=5
nuxeo.ldap.query.sizeLimit=200
nuxeo.ldap.query.timeLimit=0
nuxeo.ldap.user.searchBaseDn=
nuxeo.ldap.user.searchClass=person
nuxeo.ldap.user.searchScope=onelevel
nuxeo.ldap.user.searchBehavior=subany
nuxeo.ldap.user.readonly=true
nuxeo.ldap.user.mapping.rdn=
nuxeo.ldap.user.mapping.username=
nuxeo.ldap.user.mapping.password=
nuxeo.ldap.user.mapping.firstname=
nuxeo.ldap.user.mapping.lastname=
nuxeo.ldap.user.mapping.company=
nuxeo.ldap.user.mapping.email=
nuxeo.user.group.storage=default
nuxeo.ldap.group.searchBaseDn=
nuxeo.ldap.group.searchFilter=(|(objectClass=groupOfUniqueNames)(objectClass=groupOfURLs))
nuxeo.ldap.group.searchScope=subtree
nuxeo.ldap.group.readonly=true
nuxeo.ldap.group.mapping.rdn=
nuxeo.ldap.group.mapping.name=
nuxeo.ldap.group.mapping.label=
nuxeo.ldap.group.mapping.members.staticAttributeId=uniqueMember
nuxeo.ldap.group.mapping.members.dynamicAttributeId=memberURL
nuxeo.ldap.defaultAdministratorId=
nuxeo.ldap.defaultMembersGroup=members
nuxeo.user.emergency.enable=false
nuxeo.user.emergency.username=MyAdministrator
nuxeo.user.emergency.password=
nuxeo.user.emergency.firstname=
nuxeo.user.emergency.lastname=
Simple Configuration Example Using XML config
Create a file called
default-ldap-users-directory-config.xml
in your config directory:nxserver/config/
Then copy this content (make sure it's valid XML, sometimes what you think is a space character is actually a non-breaking space (
U+00A0
) which is invalid in XML):<?xml version="1.0"?> <component name="org.nuxeo.ecm.directory.ldap.users"> <require>org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory</require> <!-- the groups SQL directories are required to make this bundle work --> <require>org.nuxeo.ecm.directory.sql.storage</require> <extension target="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory" point="servers"> <!-- Configuration of a server connection A single server declaration can point to a cluster of replicated servers (using OpenLDAP's slapd + sluprd for instance). To leverage such a cluster and improve availability, please provide one <ldapUrl/> tag for each replica of the cluster. --> <server name="default"> <ldapUrl>ldap://localhost:389</ldapUrl> <!-- Optional servers from the same cluster for failover and load balancing: <ldapUrl>ldap://server2:389</ldapUrl> <ldapUrl>ldaps://server3:389</ldapUrl> "ldaps" means TLS/SSL connection. --> <!-- Credentials used by Nuxeo5 to browse the directory, create and modify entries. Only the authentication of users (bind) use the credentials entered through the login form if any. --> <bindDn>cn=nuxeo5,ou=applications,dc=example,dc=com</bindDn> <bindPassword>changeme</bindPassword> </server> </extension> <extension target="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory" point="directories"> <directory name="userDirectory"> <server>default</server> <schema>user</schema> <idField>username</idField> <passwordField>password</passwordField> <searchBaseDn>ou=people,dc=example,dc=com</searchBaseDn> <searchClass>person</searchClass> <!-- To additionally restricte entries you can add an arbitrary search filter such as the following: <searchFilter>(&(sn=toto*)(myCustomAttribute=somevalue))</searchFilter> Beware that "&" writes "&" in XML. --> <!-- use subtree if the people branch is nested --> <searchScope>onelevel</searchScope> <!-- using 'subany', search will match *toto*. use 'subfinal' to match *toto and 'subinitial' to match toto*. subinitial is the default behaviour--> <substringMatchType>subany</substringMatchType> <readOnly>false</readOnly> <!-- comment <cache* /> tags to disable the cache --> <cacheEntryName>ldap-user-entry-cache</cacheEntryName> <cacheEntryWithoutReferencesName>ldap-user-entry-cache-without-references</cacheEntryWithoutReferencesName> <!-- If the id field is not returned by the search, we set it with the searched entry, probably the login. Before setting it, you can change its case. Accepted values are 'lower' and 'upper', anything else will not change the case. --> <missingIdFieldCase>lower</missingIdFieldCase> <!-- Maximum number of entries returned by the search --> <querySizeLimit>200</querySizeLimit> <!-- Time to wait for a search to finish. 0 to wait indefinitely --> <queryTimeLimit>0</queryTimeLimit> <creationBaseDn>ou=people,dc=example,dc=com</creationBaseDn> <creationClass>top</creationClass> <creationClass>person</creationClass> <creationClass>organizationalPerson</creationClass> <creationClass>inetOrgPerson</creationClass> <rdnAttribute>uid</rdnAttribute> <fieldMapping name="username">uid</fieldMapping> <fieldMapping name="password">userPassword</fieldMapping> <fieldMapping name="firstName">givenName</fieldMapping> <fieldMapping name="lastName">sn</fieldMapping> <fieldMapping name="company">o</fieldMapping> <fieldMapping name="email">mail</fieldMapping> <references> <inverseReference field="groups" directory="groupDirectory" dualReferenceField="members" /> </references> </directory> </extension> <extension target="org.nuxeo.ecm.core.cache.CacheService" point="caches"> <cache name="ldap-user-entry-cache" class="org.nuxeo.ecm.core.cache.InMemoryCacheImpl"> <option name="maxSize">1000</option> <ttl>20</ttl><!-- minutes --> <option name="concurrencyLevel">500</option> </cache> <cache name="ldap-user-entry-cache-without-references" class="org.nuxeo.ecm.core.cache.InMemoryCacheImpl"> <option name="maxSize">1000</option> <ttl>20</ttl><!-- minutes --> <option name="concurrencyLevel">500</option> </cache> </extension> <extension target="org.nuxeo.ecm.platform.usermanager.UserService" point="userManager"> <userManager> <defaultAdministratorId>johndoe</defaultAdministratorId> <defaultGroup>members</defaultGroup> </userManager> </extension> </component>
Then you should edit this file:
Set the correct server:
<ldapUrl>
<bindDn>
and<bindPassword>
Set the correct LDAP config:
<searchBaseDN>
<searchClass>
<fieldMapping>
If you want Nuxeo to be able to create users in the LDAP directory:
- Make sure the user you use to access LDAP has write access
- Define the
<creationBaseDn>
and associated parameters
Define the default mapping:
- Since the Administrator user won't exists anymore, you should assign at least one user to be administrator using
<defaultAdministratorId>
- You can also choose to make all users members of the default "members" group using
<defaultGroup>
- Since the Administrator user won't exists anymore, you should assign at least one user to be administrator using
Restart the Nuxeo server, and you should now be able to authenticate against LDAP.
If you want to roll back the changes, simply delete thedefault-ldap-users-directory-config.xml
file and restart the server.
For a more detailed view about possible configuration, see:
The ldaptools/ folder in source code of the nuxeo-platform-directory-ldap
module further provides sample LDIF files and OpenLDAP configuration file to help you setup a sample OpenLDAP server you can use as a base setup to build your corporate directory.
Using Active Directory
If you use Active Directory and want to use it with Nuxeo, you need to:
- Be sure that LDAP mode is enabled on the Active Directory server,
- Get the schema info (because Active Directory schema changes depending on a lot of external factors).
Once you have this information, you can connect Nuxeo to Active Directory as it was a real LDAP server.
Active Directory users are advised to use the aggregated global catalog port number (3268 by default) instead of the default LDAP port (389) in order to avoid getting referrals request to sub-directories blocked by corporate firewalls.
Usually with AD you will have to map the field "username" to "sAMAccountName".
Also, it happens that for the bindDN, it expects only an email address, ex:
[[email protected]](mailto:[email protected])
Advanced Configuration
For more details on directories, such as configuring "multi-directories", see Data Lists and Directories.
Known Issues
LDAP Contribution Not Activated
Nuxeo Studio also generates a contribution that declares directories called userDirectory
and groupDirectory
. Those definitions could override yours and therefore disable your LDAP definition.
The solution is to disable the definition from Studio: In Studio go to Roles & Permissions > Users & Groups and active the checkbox Disable users and groups definition.
Deployment Order Issue
In the case you manipulate several directory definitions (SQL directory, LDAP directory, multi-directory), you may not have the expected behavior because you don't control the deployment order of all contributions.
A cleaner way to proceed is to define directories whose name are different from the default ones (userDirectory
for users, groupDirectory
for groups). Then you need to use the userManager to specify the name of the directories which will be used for authentication, searching, etc.
Therefore you should apply the changes described below to your existing LDAP contributions:
<!-- directory for users -->
<directory name="userLdapDirectory">
(...)
<inverseReference field="groups" directory="groupLdapDirectory"
dualReferenceField="members" />
</directory>
<!-- directory for groups -->
<directory name="groupLdapDirectory">
(...)
<ldapReference field="members" directory="userLdapDirectory" forceDnConsistencyCheck="false" staticAttributeId="uniqueMember" dynamicAttributeId="memberURL"/>
<ldapReference field="subGroups" directory="groupLdapDirectory" forceDnConsistencyCheck="false" staticAttributeId="uniqueMember" dynamicAttributeId="memberURL"/>
(...)
</directory>
<!-- definition in the user manager -->
<extension target="org.nuxeo.ecm.platform.usermanager.UserService" point="userManager">
<userManager>
(...)
<users>
<directory>userLdapDirectory</directory>
</users>
(...)
<groups>
<directory>groupLdapDirectory</directory>
</groups>
(...)
</userManager>
</extension>
See attached files for templates of LDAP configuration:
This method applies to multi-directories too.
Debug Information
If you encounter some difficulties configuring LDAP, the first step is to get more details about what happens.
In the Log4J configuration, increase the log level for org.nuxeo.ecm.directory
and org.nuxeo.runtime.model.impl
:
<category name="org.nuxeo.ecm.directory">
<priority value="DEBUG" />
</category>
<category name="org.nuxeo.runtime.model.impl">
<priority value="INFO" />
</category>
This will give you more informations such as:
- Is your XML contribution properly loaded?
Search for the component name of your contribution in the log file (for instance
org.nuxeo.ecm.directory.ldap.users
). - Did the LDAP directory initialized? If so, your "servers" extension point is working.
- What is the LDAP request sending when you try to log in Nuxeo? You must be run the same request outside Nuxeo, using your preferred LDAP tool.
Apache Directory Studio can be used to replicate the LDAP requests sent by Nuxeo to the LDAP server and check their responses. If you seek help on answers.nuxeo.com or connect.nuxeo.com please include the LDIF export of a sample user entry and a sample group entry (if you want to use the LDAP server to resolve the groups).