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 requirements or connect to legacy LDAP servers.

Download

LDAP is an Enterprise Edition feature. Download the LDAP bundle from our Nexus repository

Installing

(warning) Create a backup of your system before you install a module. Uninstalling a module is not as simple as removing the .jar file. Modules add and change configurations and may change the content. Try new modules in a test environment first. A module consists of a JAR file and may include dependent JAR files. Modules are responsible for updating their own content and configurations across versions. Be sure to keep only one version of each module and its dependencies.

To install a module:

  1. Stop the application server.
  2. Copy the module JAR files into the WEB-INF/lib directory. The location of this directory depends on the application server.
    • Tomcat: /webapps/magnoliaAuthor/WEB-INF/lib
    • JBoss: /server/default/deploy/magnoliaAuthor/WEB-INF/lib
  3. Restart the server.
  4. Go to the AdminCentral URL.
  5. Start the Web update process.
  6. Click Start up Magnolia.

Repeat the steps for each author and public instance.

Uninstalling

To uninstall a module, remove the module JAR file from the /WEB-INF/lib folder and restart Magnolia.

(warning) However, this is rarely enough. Modules add and modify configuration during installation. The use of a module also changes content. Removing all of these changes is difficult without knowing the installation tasks in detail.

To test a module, use the embedded Derby database and take a backup of your repositories folder. Install the module and try it. When you are done testing, remove the module JAR and restore the repositories folder from the backup. This way you can go back to square one.

We also recommend that you segregate the development and production environments. Take regular backups for disaster recovery so you can revert to a prior state in a routine fashion.

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.

ldap.properties

Properties to use in a ldap.properties file:

java.naming.provider.url

required

URL of the LDAP service provider.

java.naming.security.principal

optional, default is the LDAP provider's default

User or program doing the authentication. Use an appropriate DN/CN for your LDAP server. Example: CN=Administrator,CN=Users,dc=example,dc=com

java.naming.security.credentials

optional

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

java.naming.security.authentication

optional, default is none (anonymous)

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

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 service provider receives a referral despite you having set the property to ignore it will throw a PartialResultException to indicate that more results might be coming if the referral was followed. In this case the server does not 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 does not support Manage Referral Control.

To deal with the PartialResultException, create a property Configuration > /modules/ldap/config/allowPartialResults and set it to true. This property indicates what methods are used to deal with the exception:

  • true uses the hasMoreElements() and nextElement() methods
  • false uses the hasMore() and next() methods

initialSearchAttributes

required

An entry in the directory consists of a set of attributes. An attribute has a name and one or more values. The attributes are defined in a schema. The initialSearchAttributes property defines a name mapping between Magnolia-defined attributes and attributes in the directory service. This string is used to build an initial search against the server. See: Mapping LDAP attributes

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

Attributes:

  • Organization=o
  • OrganizationUnit=ou
  • CommonName=cn
  • Surname=sn
  • GivenName=givenname
  • uid=sAMAccountName
  • dn=dn
  • mail=mail
  • Password=pass
  • Language=language

groupResolverClass

optional

Define this property if you maintain user groups in LDAP. 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.MagnoliaGroupResolver resolves groups from Magnolia.

roleResolverClass

required

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

Implementations:

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

ad.properties

Properties to use in a  ldap.properties file for Microsoft Active Directory:

java.naming.provider.url

required

URL of the Active Directory service provider.

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 service provider receives a referral despite you having set the property to ignore it will throw a PartialResultException to indicate that more results might be coming if the referral was followed. In this case the server does not 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 does not support Manage Referral Control.

To deal with the PartialResultException, create a property Configuration > /modules/ldap/config/allowPartialResults and set it to true. This property indicates what methods are used to deal with the exception:

  • true uses the hasMoreElements() and nextElement() methods
  • false uses the hasMore() and next() methods

adminUserDN

required

Distinguished name (DN) of an admin user who has permissions to search the tree defined in initialSearchAttributes.

Example: CN=Administrator,CN=Users,DC=win2003srv,dc=magnolia-cms,dc=com

adminUserPassword

required

Admin user password.

ssoSlave

optional , default is false

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

java.naming.security.authentication

optional, default is none (anonymous)

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

initialSearchAttributes

required

An entry in the directory consists of a set of attributes. An attribute has a name and one or more values. The attributes are defined in a schema. The initialSearchAttributes property defines a name mapping between Magnolia-defined attributes and attributes in the directory service. This string is used to build an initial search against the server.

Example: CN=Users,DC=win2003srv,dc=magnolia-cms,dc=com

Example attributes:  

  • Organization=o
  • OrganizationUnit=ou
  • CommonName=cn
  • Surname=sn
  • GivenName=givenname
  • uid=sAMAccountName
  • dn=dn
  • mail=mail
  • Password=pass
  • Language=language

See also: Accessing properties from LDAP

groupResolverClass

optional

Define this property if you maintain user groups in Active Directory. 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.ADGroupResolver resolves groups from Active Directory.
  • info.magnolia.jaas.sp.ldap.resolver.MagnoliaGroupResolver resolves groups from Magnolia.

roleResolverClass

required

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

Implementations:

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

optional, default is memberOf

The value of this property should be memberOf. It is a computed back-link attribute maintained and calculated by Active Directory. You cannot modify this attribute.

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.

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

Explanation:

  • A user manager with realm name external will use the default LDAP property file defined under the jndi.ldap.config key since no specific property file is configured for this realm.
  • A user manager with realm name ldap will use an LDAP property file defined under the jndi.ldap.config.ldap key.
  • A user manager with realm name ad will use an Active Directory property file defined under the jndi.ldap.config.ad key.

Corresponding user manager configuration:

Node nameValue

 server

 

 security

 

 userManagers

 

 system

 

 ad

 

 class

info.magnolia.jaas.sp.ldap.ADUserManager

 realmName

 ad

 ldap

 

 class

info.magnolia.jaas.sp.ldap.LDAPUserManager

 realmName

 ldap

 external

 

 class

info.magnolia.jaas.sp.ldap.LDAPUserManager

 realmName

 external

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.

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>;
   };

Properties:

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: flag values.

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 he logs 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;
   info.magnolia.jaas.sp.ldap.LDAPAuthenticationModule requisite skip_on_previous_success=true;
   info.magnolia.jaas.sp.jcr.JCRAuthorizationModule required;
   };

Notes about example 2:

  1. JCRAuthenticationModule authenticates users who are stored only in Magnolia such as superuser and anonymous. optional means the module is not 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 does not 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.

login-config.xml for JBoss AS

For JBoss Application Server, edit the login-config.xml file instead.

Example: Authenticate against LDAP on JBoss AS

login-config.xml
<application-policy name="magnolia">
   <authentication>
      <login-module code="info.magnolia.jaas.sp.jcr.JCRAuthenticationModule" flag = "optional" />
      <login-module code="info.magnolia.jaas.sp.ldap.LDAPAuthenticationModule" flag = "requisite">
          <module-option name="realm">admin</module-option>
          <module-option name="skip_on_previous_success">true</module-option>
          <module-option name="jndi.ldap.config">ldap.properties</module-option>
      </login-module>
      <login-module code="info.magnolia.jaas.sp.jcr.JCRAuthorizationModule" flag = "required" />
   </authentication>
</application-policy>

User manager

You also need to configure an external UserManager.

(warning) Make sure the nodes under userManagers are ordered so that external is before admin but after system. Any other order may result in 401 errors (authentication failed) during publishing and unpublishing of content.

Node nameValue

 server

 

 security

 

 userManagers

 

 system

 

 external

 

 class

info.magnolia.jaas.sp.ldap.LDAPUserManager

 realmName

 external

 admin

 

 public

 

Properties:

allowCrossRealmDuplicateNames

optional, default is false

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

class

required

A class that implements the 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.DelegatingUserManagerretrieves the user's ACLs.
  • info.magnolia.cms.security.SystemUserManager manages system users such as anonymous and superuser.
lockTimePeriod

optional, default is 0

Time in minutes the account is locked after maxFailedLoginAttempts is reached.

maxFailedLoginAttempts

optional, default is 5

Number of failed attempts allowed before locking the account.

realmName

required

Realm name corresponding to JAAS login configuration.


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 two create users with the same name in different realms when replicating LDAP/AD users in the repository. By default, Magnolia does not allow the same user name to be repeated.  

Node nameValue

 security

 

 userManagers

 

 system

 

 external

 

 admin

 

 allowCrossRealmDuplicatNames

true

 class

info.magnolia.cms.security.MgnlUserManager

 lockTimePeriod

 0

 maxFailedLoginAttempts

 5

 realmName

 admin

 public

 

See also: Configuring multiple directory servers

Mapping LDAP attributes

Before using the connector, map Magnolia-specific attributes to LDAP attributes. For example, in Organization=o, "Organization" is a keyword for Magnolia and "o" refers to the attribute name as defined for the LDAP server.

Organization=o
OrganizationUnit=ou
CommonName=cn
Surname=sn
GivenName=givenname
uid=sAMAccountName
dn=dn
mail=mail
GroupId=memberOf
Password=pass
Language=language

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. Examples of default Magnolia groups are editors and publishers which correspond to the responsibilities users have in the content workflow.

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

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 role is the element that grants the user a 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 in order to grant users the permissions they need. This minimizes the number of groups you need to create in Magnolia.

MagnoliaLDAP

Roles

Groups

Groups

Users

editor
workflow-base

editors

editors

jsmith
eallen
cappleton

publisher
workflow-base

publishers

publishers

bleroy
dmillet
vrobbins

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 does not provide ready-made resolver classes for every possible LDAP product but you can write your own class. Implement the  NameResolver  interface and  the methods to fetch group names from the directory.

Testing and validating LDAP Configuration

The magnolia-ldap-tester artifact is a self-contained executable jar which can be executed with:

java -jar magnolia-ldap-tester-<version>.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

Do not expect to see any groups or roles assigned. The tester tool does not connect to Magnolia in any way. It connects to the LDAP. It is normal for group assignments handled in Magnolia not to show up.

#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))