LDAP Connector module

Security and authentication Unbundled: Extension

Edition DX Core

License

MLA

Issues

Maven site

Latest

2.0.0

Magnolia LDAP Connector is a JAAS login module that connects to any LDAP v3 directory service. The LDAP Connector is used in intranet environments where an enterprise user management infrastructure already exists. With JAAS you can meet single sign-on (SSO) requirements or connect to legacy LDAP servers.

Installing with Maven

Maven is the easiest way to install the module. Add the following to your bundle:

<dependency>
  <groupId>info.magnolia</groupId>
  <artifactId>magnolia-ldap</artifactId>
  <version>2.0.0</version> (1)
</dependency>
1 Should you need to specify the module version, do it using <version>.

Module configuration

Since module version 1.9, the configuration of the following is done directly in the User Manager:

  • allowPartialResults

  • ignoreGroupsWithIllegalName

  • pageSize

  • envPropertiesPredicate

LDAP configuration

An LDAP configuration file tells Magnolia where to find your LDAP directory server. The file also says whether Magnolia should resolve users, groups, or both from the directory.

The LDAP Connector module bundle provides two sample files in the configuration-samples folder:

  • ldap.properties defines an LDAP server.

  • ad.properties defines an Active Directory server.

Properties (LDAP and/or Active Directory)

Properties used in the ldap.properties and/or ad.properties file(s):

File(s) Property Description

both

java.naming.provider.url

required

URL of the LDAP/AD service provider.

Example: ldap://ldap.example.com/

both

java.naming.security.principal

required, default is the LDAP provider’s default

User or program doing the authentication. Use an appropriate DN/CN for your server.

Example: CN=Administrator,CN=Users,dc=example,dc=com

Originally interchangeable with the now deprecated adminUserDN property but takes precedence if both are specified in the file.

both

java.naming.security.credentials

required

Password or encrypted data such as a digital certificate that the implementation uses to authenticate the client.

Originally interchangeable with the now deprecated adminUserPassword property but takes precedence if both are specified in the file.

both

java.naming.security.authentication

optional, default is `none`

Authentication mechanism (password encryption) used. Possible values are none, simple, or a specific authentication mechanism such as DIGEST-MD5.

both

java.naming.referral

optional, default is `ignore`

Indicates to the service provider how to handle referrals. Valid values are ignore, follow and throw.

If the LDAP/AD service provider receives a referral despite you having set the property to ignore, it throws a PartialResultException to indicate that more results may be coming if the referral was followed. In this case, the server doesn’t support the Manage Referral control and supports referral updates in some other way. See Oracle: Referrals in the JNDI. Windows Active Directory is an example of a directory service which doesn’t support Manage Referral control.

To deal with the PartialResultException, create a property in Configuration > /modules/ldap/config/allowPartialResults and set it to true.

both

java.naming.factory.initial

optional (but recommended)

The class name of the of the initial context. The class must implement the javax.naming.directory.DirContext interface or LDAP requests from Magnolia fail.

The default value for java.naming.factory.initial depends on your container or Java configuration. For example, the default configuration for Apache Tomcat specifies the class org.apache.naming.SelectorContext, which doesn’t implement the java.naming.directory.DirContext interface. When running in Tomcat, the class com.sun.jndi.ldap.LdapCtxFactory can be used.

both

initialSearchAttributes

required

Defines the initial connect point to the directory service.

Example: initialSearchAttributes=CN=Users,dc=example,dc=com

both

Organization\ OrganizationUnit\ CommonName\ Surname\ GivenName\ uid\ dn\ mail\ Password\ Language

required

Name mapping(s) taking the form <property>=<value>, for example:

CommonName=cn
mail=mail
Password=pass
Language=language
The properties shown on the left are just a few examples. If necessary, more (custom) properties may be created to allow smooth mapping of names.

both

userSearchFilter

optional

When searching a user from a wide initialSearchAttribute, a custom filter may be useful. Be aware that attribute used for resolving LDAP_USER_ID needs to be same as mapped uid attribute (see mappings above).

Example: userSearchFilter=(&(objectClass=user)(sAMAccountName=LDAP_USER_ID))

It’s also possible to reuse the mapped uid attribute from the configuration above: allUsersSearchFilter=(&(objectClass=user)(UID_ATTRIBUTE=LDAP_USER_ID))

both

userSearchFilter

optional

A custom filter can be used also when searching all users from a wide initialSearchAttribute.

Example: allUsersSearchFilter=(objectClass=user)

ADUserManager default users search filter is: (&(objectCategory=person)(objectClass=user))

both

groupResolverClass

required (if roleResolverClass is not used)

The value is a class responsible for resolving groups assigned to a user. The class must implement the info.magnolia.jaas.sp.ldap.resolver.NameResolver interface.

Implementations:

  • info.magnolia.jaas.sp.ldap.resolver.OpenLDAPGroupResolver resolves groups from any LDAP directory.

  • info.magnolia.jaas.sp.ldap.resolver.ADGroupResolver resolves groups from Active Directory.

  • info.magnolia.jaas.sp.ldap.resolver.MagnoliaGroupResolver resolves groups from Magnolia.

both

roleResolverClass

required (if groupResolverClass is not used)

A class responsible for resolving roles assigned to a user. The class must implement the info.magnolia.jaas.sp.ldap.resolver.NameResolver interface. Roles can’t be maintained in LDAP, they must be in Magnolia.

Implementation:

  • info.magnolia.jaas.sp.ldap.resolver.MagnoliaRoleResolver resolves roles from Magnolia.

ad.

ssoSlave

optional, default is false

Set ssoSlave=true if this Magnolia instance is a slave server in a single sign-on (SSO) environment.

ad.

userMembershipAttribute

required (only if ADGroupResolver is used)

The name of the user attribute which specifies the groups the user is a member of.

Example: userMembershipAttribute=memberOf

ldap.

groupSearchFilter

required (if OpenLDAPGroupResolver is used)

A filter used to find groups the user is a member of.

Example: groupSearchFilter=(&(objectClass=groupOfNames)(member=MEMBERSHIP_VALUE))

ldap.

groupMembershipAttributeValue

required (if OpenLDAPGroupResolver is used)

The value of the dn attribute to be passed to MEMBERSHIP_VALUE in groupSearchFilter.

Example: groupMembershipAttributeValue=dn

both

groupIdAttribute

required (only if either OpenLDAPGroupResolver or ADGroupResolver is used)

The name of the group ID attribute in LDAP/AD.

Example: groupIdAttribute=cn

both

groupSearchContext

optional (only if either OpenLDAPGroupResolver or ADGroupResolver is used)

A subtree for groups in the LDAP/AD structure if groups are managed in a different subtree than the users. If not set, then the initialSearchAttributes is used.

Example: groupSearchContext=cn=groups,dc=example,dc=com

both

groupsSearchFilter

optional (only if either OpenLDAPGroupResolver or ADGroupResolver is used), default values are:

  • For the LDAP resolver: (&(objectClass=groupOfNames)GROUP_IDS_SUBSTITUTION)

  • For the AD resolver: (&(objectClass=group)GROUP_IDS_SUBSTITUTION)

A filter for searching groups in LDAP/AD.

both

groupMembershipAttribute

required (only if either OpenLDAPGroupResolver or ADGroupResolver is used)

The name of the group attribute which specifies the members belonging to the group.

Example: groupMembershipAttribute=member

Deprecated properties:

  • adminUserDN

  • adminUserPassword

Instead, use java.naming.security.principal and java.naming.security.credentials properties respectively.

magnolia.properties

Put the ldap.properties or ad.properties file inside your Magnolia webapp, for example in /<CATALINA_HOME>/webapps/<contextPath>/WEB-INF/config.

Reference the file location from a magnolia.properties file using the jndi.ldap.config property.

Set the value to an absolute or relative path inside the webapp. You can also use the ${magnolia.home} variable.

magnolia.properties
jndi.ldap.config=WEB-INF/config/ldap.properties

Configuring multiple directory servers

To configure multiple LDAP and AD directories, use the pattern jndi.ldap.config.<realmName> where realmName corresponds to a realm name in the User Manager.

Example: Configuring multiple directory servers in magnolia.properties.
jndi.ldap.config.ad=WEB-INF/config/ad.properties (1)
jndi.ldap.config.ldap=WEB-INF/config/ldap.properties (2)
jndi.ldap.config=WEB-INF/config/default-ldap.properties (3)
1 A user manager with realm name ad uses an Active Directory property file defined under the jndi.ldap.config.ad key.
2 A user manager with realm name ldap uses an LDAP property file defined under the jndi.ldap.config.ldap key.
3 A user manager with realm name external uses the default LDAP property file defined under the jndi.ldap.config key since no specific property file is configured for this realm.

Corresponding User Manager configuration:

User manager configuration

A custom configuration resolver

From LDAP Connector module 1.9+, you can write your own configuration resolver in JAVA. Add the following component to your module descriptor:

<components>
 <id>main</id>
 <component>
  <type>info.magnolia.jaas.sp.ldap.config.ConfigResolver</type>
  <implementation>your-own-resolver-class</implementation>
 </component>
</components>

Change the implementation class accordingly, and make sure that your module depends on (that is, it’s loaded after) the LDAP Connector module.

JAAS login configuration

Magnolia uses the Java Authentication and Authorization Service (JAAS) to authenticate users. When you store users in a directory outside of Magnolia, configure the directory as a LoginModule.

You can list several LoginModules. Authentication proceeds down the module list in the order you specify with flags, see javax.security.auth.login.Configuration.

Depending on the servlet container you use, the configuration for JAAS is slightly different.

For more information, see * JAAS security setup.

jaas.config for Tomcat

For the Tomcat application server, create a jaas.config file and list the LoginModules in the following format:

jaas.config syntax
magnolia {
   <LoginModule> <flag> <options>;
   <LoginModule> <flag> <options>;
   <LoginModule> <flag> <options>;
   };
Property Description

LoginModule

required

A class that implements the desired authentication technology.

Implementations:

  • info.magnolia.jaas.sp.jcr.JCRAuthenticationModule authenticates against Magnolia.

  • info.magnolia.jaas.sp.ldap.LDAPAuthenticationModule authenticates against any LDAP directory.

  • info.magnolia.jaas.sp.ldap.ADAuthenticationModule authenticates against Active Directory.

  • info.magnolia.jaas.sp.jcr.JCRAuthorizationModule retrieves the user’s ACLs.

Set also the groupResolverClass and roleResolverClass properties in ldap.properties.

flag

required

The flag indicates whether success of the preceding LoginModule is required, requisite, sufficient, or optional. If you only have one LoginModule then the flag must be required.

See the flag values in javax.security.auth.login.Configuration.

options

optional

Options is a space-separated list of LoginModule-specific values which are passed directly to the LoginModule. The options are defined by the LoginModule itself, and control its behavior.

Options for JCRAuthenticationModule module:

  • realm: Restrict the login to a certain realm.

    Valid values: system, external, admin, public.

  • use_realm_callback: Allow the client to define the realm they log into.

    Values: true, false. Default is false.

  • skip_on_previous_success: A Magnolia-specific option to define if this module needs to be skipped based on previous (in JAAS module chain) module status.

    Values: true, false. If true this module is skipped if the previous module did a successful login.

    Example 1

    Authenticate against Magnolia on Tomcat

    jaas.config
    magnolia {
       info.magnolia.jaas.sp.jcr.JCRAuthenticationModule requisite;
       info.magnolia.jaas.sp.jcr.JCRAuthorizationModule required;
       };
    Example 2

    Authenticate against LDAP on Tomcat

    jaas.config
    magnolia {
       info.magnolia.jaas.sp.jcr.JCRAuthenticationModule optional; (1)
       info.magnolia.jaas.sp.ldap.LDAPAuthenticationModule requisite skip_on_previous_success=true; (2)
       info.magnolia.jaas.sp.jcr.JCRAuthorizationModule required; (3)
       };
    1 JCRAuthenticationModule authenticates users who are stored only in Magnolia such as superuser and anonymous. optional means the module isn’t required to succeed. Authentication proceeds to the next module whether the user is found or not.
    2 LDAPAuthenticationModule authenticates users who are stored in LDAP. requisite means that if the login module succeeds, authentication continues down the list. If the module fails, authentication doesn’t proceed down the list. This module is skipped if the previous module was successful. This module could also be info.magnolia.jaas.sp.ldap.ADAuthenticationModule.
    3 JCRAuthorizationModule is required to succeed.

User manager

You must also configure an external UserManager.

Make sure your external UserManager is placed before the admin but after the system user managers. Any other order may result in 401 errors (authentication failed) during publishing and unpublishing of content.

User manager node

Property Description

allowCrossRealmDuplicateNames

optional, default is false

Allows duplicate usernames in different realms. Only applicable to admin realm.

class

required

A class that implements the info.magnolia.cms.security.UserManager interface.

Implementations:

  • info.magnolia.cms.security.MgnlUserManager manages users stored in Magnolia.

  • info.magnolia.cms.security.ExternalUserManager manages JAAS users.

  • info.magnolia.cms.security.HierarchicalUserManager is a variation of MgnlUserManager that stores users hierarchically using the structure /<path>/<first letter of username>/<first two letters of username> such as /public/j/js/jsmith.

  • info.magnolia.cms.security.DelegatingUserManager retrieves the user’s ACLs.

  • info.magnolia.cms.security.SystemUserManager manages system users such as anonymous and superuser.

disableCache

optional, default is false

Allows to disable caching if set to true.

realmName

required

Realm name corresponding to JAAS login configuration.

allowPartialResults

optional, default is false

Indicates what methods are used to deal with the PartialResultException exception thrown by the LDAP service provider (see the java.naming.referral property).

  • true uses the hasMoreElements() and nextElement() methods.

  • false uses the hasMore() and next() methods.

connectionFactory

optional

A subnode that allows you to specify a custom connectionFactory.

     class

The class that implements the connectionFactory.

The default class used is magnolia.jaas.sp.ldap.connection.DefaultConnectionFactory.

Two additional implementations are available:

  • magnolia.jaas.sp.ldap.connection.JavaBeanBasedConnectionFactory

    This implementation supports defining properties securityPrincipal and securityCredentials. For usage please see Apache’s Generic JavaBean Resources.

  • magnolia.jaas.sp.ldap.connection.JNDIResourceConnectionFactory

    This is a JNDI resource based factory. It can be used with com.sun.jndi.ldap.LdapCtxFactory or with magnolia.jaas.sp.ldap.connection.jndiresources.MagnoliaLdapContextFactory. For usage please see Apache’s Adding Custom Resource Factories.

     envPropertiesPredicate

optional

A subnode that specifies the envPropertiesPredicate.

If not defined explicitly, then the predicate accepts anything within the following namespaces:

  • java.naming.* (except credentials and principal)

  • com.sun.jndi.ldap.*

         class

The class that implements the envPropertiesPredicate.

The default class is magnolia.jaas.sp.ldap.connection.EnvPropertiesDefaultPredicate.

     passwordDecoder

optional

A subnode that defines the decoding method of the admin password used by the connectionFactory.

The decoder is available only with the DefaultConnectionFactory and JavaBeanBasedConnectionFactory connection classes. However, you can also write your own password decoder.

         class

The decoder is available in three implementations:

  • magnolia.jaas.sp.ldap.connection.password.NoOpPasswordDecoder

    This implementation returns a password without any decoding.

  • magnolia.jaas.sp.ldap.connection.password.ActivationKeyBasedPasswordDecoder

    This implementation uses the same set of keys as activation. To get an encoded password, use the SecurityUtil.encrypt("password") method.

  • magnolia.jaas.sp.ldap.connection.password.PasswordManagerBasedPasswordDecoder

    This implementation loads the admin’s LDAP password from the Password Manager module.

pageSize

optional, default is 500

Specifies the number of objects to be returned in a single search result.

User managers and caching

By default, the ad and ldap user managers use a basic cache (Cache modules) to avoid repeated calls to LDAP/AD. If Ehcache is used, then the default configuration is automatically bootstrapped into /modules/cache/config/cacheFactory/caches/ldap-user-manager-cache. You can disable caching by adding the disableCache property to the manager’s node and setting it to true, for example.

User managers and caching node

Accessing properties from LDAP

If you need to access more user properties than name, full name and language, extend info.magnolia.jaas.sp.ldap.LDAPAuthenticationModule#setEntity to push the desired properties into the Entity object, and the info.magnolia.cms.security.ExternalUserManager / info.magnolia.cms.security.ExternalUser pair to expose it.

Same-name users in different realms

If you are resolving roles or groups, add the allowCrossRealmDuplicateNames property under /server/security/userManagers/admin and set its value to true. This property allows you to create users with the same name in different realms when replicating LDAP/AD users in the repository. By default, Magnolia doesn’t allow the same user name to be repeated.

Same-name users in different realms

Groups and roles

LDAP typically mirrors the organization structure. If your company has a Marketing department, then create a marketing group in the LDAP directory and assign employees to the group. Magnolia also organizes users into groups.

Magnolia also has roles. A role grants a user permission to do something. For example, the editor role grants the user permission to edit content. Permissions are configured using access control lists. A role can be assigned directly to a user or to a group.

Groups and roles diagram

When you authenticate users against an LDAP directory, a resolver class finds the groups and roles the user belongs to. This process is called resolving. Since the role is the element that grants the user permission to do something, you must resolve at least roles. You can optionally also resolve groups.

Group resolving

A groupResolverClass configured in ldap.properties finds groups in the LDAP directory and matches them to groups in Magnolia. The group names must match exactly.

Choose a resolver depending on where the groups are stored:

  • info.magnolia.jaas.sp.ldap.resolver.MagnoliaGroupResolver resolves groups from Magnolia.

  • info.magnolia.jaas.sp.ldap.resolver.OpenLDAPGroupResolver resolves groups from any LDAP directory.

  • info.magnolia.jaas.sp.ldap.resolver.ADGroupResolver resolves groups from Active Directory.

Best practice

When you store groups in LDAP, create one matching group per role in Magnolia. Assign roles to the group in Magnolia to grant users the permissions they need. This minimizes the number of groups you need to create in Magnolia.

Magnolia LDAP

Roles

Groups

Groups

Users

  • editor

  • workflow-base

editors

editors

  • jsmith

  • eallen

  • cappleton

  • publisher

  • workflow-base

publishers

publishers

  • bleroy

  • dmillet

  • vrobbins

When creating a group name, make sure that it doesn’t contain an illegal character. See also the ignoreGroupsWithIllegalName property in module configuration.

Role resolving

A roleResolverClass configured in ldap.properties finds roles. Roles must always be stored in Magnolia, they cannot be stored in the LDAP directory. The reason is that the ACLs that grant permissions are attached to roles.

Magnolia provides one role resolver:

  • info.magnolia.jaas.sp.ldap.resolver.MagnoliaRoleResolver resolves roles from the userroles workspace in Magnolia.

Implementing your own resolver

Magnolia doesn’t provide ready-made resolver classes for every possible LDAP product but you can write your own class. Implement the info.magnolia.jaas.sp.ldap.resolver.NameResolver interface and the methods to fetch group names from the directory.

Testing and validating LDAP configuration

You can use the magnolia-ldap-tester, a standalone module for testing ldap/ad configuration outside of Magnolia. The module is available from Magnolia Nexus: magnolia-ldap-tester-2.0.0.jar

Use the following command to execute the jar:

java -jar magnolia-ldap-tester-2.0.0.jar <LoginModule class name> <config.properties> <username> <password>

<LoginModule class name> should be either info.magnolia.jaas.sp.ldap.LDAPAuthenticationModule or info.magnolia.jaas.sp.ldap.ADAuthenticationModule, depending on which one you’re using in jaas.config (or login-config.xml with JBoss).

The tool simulates a user login with the given credentials and configuration, outputs the main results, and logs everything else in magnolia-ldap-tester.log.

A successful login attempt looks like this in the log:

INFO i.m.jaas.sp.ldap.ConnectionFactory - Trying to log in as
   cn=jsmith,dc=example,dc=com with a password.
DEBUG i.m.jaas.sp.ldap.ConnectionFactory - Login succeeded.
DEBUG i.m.j.s.l.Tester$MockSecuritySupport - Getting user jsmith from realm admin
INFO info.magnolia.ldap.tool.LDAPTester - Login result: true
INFO info.magnolia.ldap.tool.LDAPTester - Commit result: true
DEBUG info.magnolia.ldap.tool.LDAPTester - Subject:
DEBUG info.magnolia.ldap.tool.LDAPTester - User: null
INFO info.magnolia.ldap.tool.LDAPTester -
   Properties: {title=jsmith,
   email=john.smith@example.com,
   name=jsmith,
   fullName=jsmith,
   password=secret}
DEBUG info.magnolia.ldap.tool.LDAPTester -
   State: {groupNames=[],
   statusValue=1,
   roleNames=[]}
INFO info.magnolia.ldap.tool.LDAPTester - Group names: (none)
INFO info.magnolia.ldap.tool.LDAPTester - Role names: (none)
DEBUG info.magnolia.ldap.tool.LDAPTester - AttributesMap

Don’t expect to see any groups or roles assigned. The tester tool doesn’t connect to Magnolia in any way. It connects to the LDAP. It’s normal for group assignments handled in Magnolia to not show up.

Feedback

DX Core

×

Location

This widget lets you know where you are on the docs site.

You are currently perusing through the DX Core docs.

Main doc sections

DX Core Headless PaaS Legacy Cloud Incubator modules