<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="Core.LDAPConfiguration">
  <title>LDAP Configuration</title>

  <para>You may decide to make eXo users to be mapped to an existing
  directory. eXo provides a flexible implementation of its OrganizationService
  on top of LDAP. It can be used on any LDAP compliant directory and even
  Active Directory. This page will guide you how to configure eXo Platform to
  work with your directory.</para>

  <section id="Core.LDAPConfiguration.Quickstart">
    <title>Quickstart</title>

    <para>If you just want to have a look at how eXo works with LDAP, eXo
    comes with a predefined LDAP configuration. You just need to activate it
    and eXo will create everything it needs to work at startup.</para>

    <para>You need to have a working LDAP server and a user with write
    permissions.</para>

    <itemizedlist>
      <listitem>
        <para>0pen <filename>idm-configuration.xml</filename> located in this
        path <emphasis
        role="bold">eXo-PLF-3.5.x-tomcat-bundle/webapps/platform-extension/WEB-INF/conf/organization</emphasis>
        comment this tag:</para>

        <programlisting language="xml">&lt;value&gt;war:/conf/organization/picketlink-idm/picketlink-idm-config.xml&lt;/value&gt;
        </programlisting>

        <para>and add this tag:</para>

        <programlisting language="xml">&lt;value&gt;war:/conf/organization/picketlink-idm/picketlink-idm-ldap-config.xml&lt;/value&gt;
        </programlisting>
      </listitem>
    </itemizedlist>

    <itemizedlist>
      <listitem>
        <para>Under <emphasis
        role="bold">eXo-PLF-3.5.x-tomcat-bundle/webapps/platform-extension/WEB-INF/conf/organization/picketlink-idm</emphasis>
        add the <filename>picketlink-idm-ldap-config.xml</filename>
        file.</para>

        <para>The content of this file is as follows:</para>

        <programlisting language="xml">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;jboss-identity xmlns="urn:picketlink:idm:config:v1_0_0_ga"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:picketlink:idm:config:v1_0_0_ga identity-config.xsd"&gt;
  &lt;realms&gt;
    &lt;realm&gt;
      &lt;id&gt;idm_realm_sample-portal&lt;/id&gt;
      &lt;repository-id-ref&gt;DefaultPortalRepository&lt;/repository-id-ref&gt;
      &lt;identity-type-mappings&gt;
        &lt;user-mapping&gt;USER&lt;/user-mapping&gt;
      &lt;/identity-type-mappings&gt;
      &lt;options&gt;
        &lt;option&gt;
          &lt;name&gt;cache.providerRegistryName&lt;/name&gt;
          &lt;value&gt;apiCacheProvider&lt;/value&gt;
        &lt;/option&gt;
      &lt;/options&gt;
    &lt;/realm&gt;
    &lt;realm&gt;
      &lt;id&gt;idm_realm&lt;/id&gt;
      &lt;repository-id-ref&gt;PortalRepository&lt;/repository-id-ref&gt;
      &lt;identity-type-mappings&gt;
        &lt;user-mapping&gt;USER&lt;/user-mapping&gt;
      &lt;/identity-type-mappings&gt;
      &lt;options&gt;
        &lt;option&gt;
          &lt;name&gt;template&lt;/name&gt;
          &lt;value&gt;true&lt;/value&gt;
        &lt;/option&gt;
        &lt;option&gt;
          &lt;name&gt;cache.providerRegistryName&lt;/name&gt;
          &lt;value&gt;apiCacheProvider&lt;/value&gt;
        &lt;/option&gt;
      &lt;/options&gt;
    &lt;/realm&gt;
  &lt;/realms&gt;
  &lt;repositories&gt;
    &lt;repository&gt;
      &lt;id&gt;PortalRepository&lt;/id&gt;
      &lt;class&gt;org.picketlink.idm.impl.repository.FallbackIdentityStoreRepository&lt;/class&gt;
      &lt;external-config/&gt;
      &lt;default-identity-store-id&gt;HibernateStore&lt;/default-identity-store-id&gt;
      &lt;default-attribute-store-id&gt;HibernateStore&lt;/default-attribute-store-id&gt;
      &lt;identity-store-mappings&gt;
        &lt;identity-store-mapping&gt;
          &lt;identity-store-id&gt;PortalLDAPStore&lt;/identity-store-id&gt;
          &lt;identity-object-types&gt;
            &lt;identity-object-type&gt;USER&lt;/identity-object-type&gt;
            &lt;identity-object-type&gt;platform_type&lt;/identity-object-type&gt;
            &lt;identity-object-type&gt;organization_type&lt;/identity-object-type&gt;
          &lt;/identity-object-types&gt;
          &lt;options/&gt;
        &lt;/identity-store-mapping&gt;
      &lt;/identity-store-mappings&gt;
      &lt;options&gt;
        &lt;option&gt;
          &lt;name&gt;allowNotDefinedAttributes&lt;/name&gt;
          &lt;value&gt;true&lt;/value&gt;
        &lt;/option&gt;
      &lt;/options&gt;
    &lt;/repository&gt;
    &lt;repository&gt;
      &lt;id&gt;DefaultPortalRepository&lt;/id&gt;
      &lt;class&gt;org.picketlink.idm.impl.repository.WrapperIdentityStoreRepository&lt;/class&gt;
      &lt;external-config/&gt;
      &lt;default-identity-store-id&gt;HibernateStore&lt;/default-identity-store-id&gt;
      &lt;default-attribute-store-id&gt;HibernateStore&lt;/default-attribute-store-id&gt;
    &lt;/repository&gt;
  &lt;/repositories&gt;
  &lt;stores&gt;
    &lt;attribute-stores/&gt;
    &lt;identity-stores&gt;
      &lt;identity-store&gt;
        &lt;id&gt;HibernateStore&lt;/id&gt;
        &lt;class&gt;org.picketlink.idm.impl.store.hibernate.HibernateIdentityStoreImpl&lt;/class&gt;
        &lt;external-config/&gt;
        &lt;supported-relationship-types&gt;
          &lt;relationship-type&gt;JBOSS_IDENTITY_MEMBERSHIP&lt;/relationship-type&gt;
          &lt;relationship-type&gt;JBOSS_IDENTITY_ROLE&lt;/relationship-type&gt;
        &lt;/supported-relationship-types&gt;
        &lt;supported-identity-object-types&gt;
          &lt;identity-object-type&gt;
            &lt;name&gt;USER&lt;/name&gt;
            &lt;relationships/&gt;
            &lt;credentials&gt;
              &lt;credential-type&gt;PASSWORD&lt;/credential-type&gt;
            &lt;/credentials&gt;
            &lt;attributes/&gt;
            &lt;options/&gt;
          &lt;/identity-object-type&gt;
        &lt;/supported-identity-object-types&gt;
        &lt;options&gt;
          &lt;option&gt;
            &lt;name&gt;hibernateSessionFactoryRegistryName&lt;/name&gt;
            &lt;value&gt;hibernateSessionFactory&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;populateRelationshipTypes&lt;/name&gt;
            &lt;value&gt;true&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;populateIdentityObjectTypes&lt;/name&gt;
            &lt;value&gt;true&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;allowNotDefinedIdentityObjectTypes&lt;/name&gt;
            &lt;value&gt;true&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;allowNotDefinedAttributes&lt;/name&gt;
            &lt;value&gt;true&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;isRealmAware&lt;/name&gt;
            &lt;value&gt;true&lt;/value&gt;
          &lt;/option&gt;
        &lt;/options&gt;
      &lt;/identity-store&gt;
      &lt;identity-store&gt;
        &lt;id&gt;PortalLDAPStore&lt;/id&gt;
        &lt;class&gt;org.picketlink.idm.impl.store.ldap.LDAPIdentityStoreImpl&lt;/class&gt;
        &lt;external-config/&gt;
        &lt;supported-relationship-types&gt;
          &lt;relationship-type&gt;JBOSS_IDENTITY_MEMBERSHIP&lt;/relationship-type&gt;
        &lt;/supported-relationship-types&gt;
        &lt;supported-identity-object-types&gt;
          &lt;identity-object-type&gt;
            &lt;name&gt;USER&lt;/name&gt;
            &lt;relationships/&gt;
            &lt;credentials&gt;
              &lt;credential-type&gt;PASSWORD&lt;/credential-type&gt;
            &lt;/credentials&gt;
            &lt;attributes&gt;
              &lt;attribute&gt;
                &lt;name&gt;firstName&lt;/name&gt;
                &lt;mapping&gt;cn&lt;/mapping&gt;
                &lt;type&gt;text&lt;/type&gt;
                &lt;isRequired&gt;false&lt;/isRequired&gt;
                &lt;isMultivalued&gt;false&lt;/isMultivalued&gt;
                &lt;isReadOnly&gt;false&lt;/isReadOnly&gt;
              &lt;/attribute&gt;
              &lt;attribute&gt;
                &lt;name&gt;lastName&lt;/name&gt;
                &lt;mapping&gt;sn&lt;/mapping&gt;
                &lt;type&gt;text&lt;/type&gt;
                &lt;isRequired&gt;false&lt;/isRequired&gt;
                &lt;isMultivalued&gt;false&lt;/isMultivalued&gt;
                &lt;isReadOnly&gt;false&lt;/isReadOnly&gt;
              &lt;/attribute&gt;
              &lt;attribute&gt;
                &lt;name&gt;email&lt;/name&gt;
                &lt;mapping&gt;mail&lt;/mapping&gt;
                &lt;type&gt;text&lt;/type&gt;
                &lt;isRequired&gt;false&lt;/isRequired&gt;
                &lt;isMultivalued&gt;false&lt;/isMultivalued&gt;
                &lt;isReadOnly&gt;false&lt;/isReadOnly&gt;
                &lt;isUnique&gt;true&lt;/isUnique&gt;
              &lt;/attribute&gt;
            &lt;/attributes&gt;
            &lt;options&gt;
              &lt;option&gt;
                &lt;name&gt;idAttributeName&lt;/name&gt;
                &lt;value&gt;uid&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;passwordAttributeName&lt;/name&gt;
                &lt;value&gt;userPassword&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;ctxDNs&lt;/name&gt;
                &lt;value&gt;ou=People,o=portal,o=gatein,dc=example,dc=com&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;allowCreateEntry&lt;/name&gt;
                &lt;value&gt;true&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;createEntryAttributeValues&lt;/name&gt;
                &lt;value&gt;objectClass=top&lt;/value&gt;
                &lt;value&gt;objectClass=inetOrgPerson&lt;/value&gt;
                &lt;value&gt;sn= &lt;/value&gt;
                &lt;value&gt;cn= &lt;/value&gt;
              &lt;/option&gt;
            &lt;/options&gt;
          &lt;/identity-object-type&gt;
          &lt;identity-object-type&gt;
            &lt;name&gt;platform_type&lt;/name&gt;
            &lt;relationships&gt;
              &lt;relationship&gt;
                &lt;relationship-type-ref&gt;JBOSS_IDENTITY_MEMBERSHIP&lt;/relationship-type-ref&gt;
                &lt;identity-object-type-ref&gt;USER&lt;/identity-object-type-ref&gt;
              &lt;/relationship&gt;
              &lt;relationship&gt;
                &lt;relationship-type-ref&gt;JBOSS_IDENTITY_MEMBERSHIP&lt;/relationship-type-ref&gt;
                &lt;identity-object-type-ref&gt;platform_type&lt;/identity-object-type-ref&gt;
              &lt;/relationship&gt;
            &lt;/relationships&gt;
            &lt;credentials/&gt;
            &lt;attributes/&gt;
            &lt;options&gt;
              &lt;option&gt;
                &lt;name&gt;idAttributeName&lt;/name&gt;
                &lt;value&gt;cn&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;ctxDNs&lt;/name&gt;
                &lt;value&gt;ou=Platform,o=portal,o=gatein,dc=example,dc=com&lt;/value&gt;
              &lt;/option&gt;
              &lt;!--&lt;option&gt;--&gt;
              &lt;!--&lt;name&gt;entrySearchFilter&lt;/name&gt;--&gt;
              &lt;!--&lt;value&gt;&lt;/value&gt;--&gt;
              &lt;!--&lt;/option&gt;--&gt;
              &lt;option&gt;
                &lt;name&gt;allowCreateEntry&lt;/name&gt;
                &lt;value&gt;true&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;parentMembershipAttributeName&lt;/name&gt;
                &lt;value&gt;member&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;isParentMembershipAttributeDN&lt;/name&gt;
                &lt;value&gt;true&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;allowEmptyMemberships&lt;/name&gt;
                &lt;value&gt;true&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;createEntryAttributeValues&lt;/name&gt;
                &lt;value&gt;objectClass=top&lt;/value&gt;
                &lt;value&gt;objectClass=groupOfNames&lt;/value&gt;
              &lt;/option&gt;
            &lt;/options&gt;
          &lt;/identity-object-type&gt;
          &lt;identity-object-type&gt;
            &lt;name&gt;organization_type&lt;/name&gt;
            &lt;relationships&gt;
              &lt;relationship&gt;
                &lt;relationship-type-ref&gt;JBOSS_IDENTITY_MEMBERSHIP&lt;/relationship-type-ref&gt;
                &lt;identity-object-type-ref&gt;USER&lt;/identity-object-type-ref&gt;
              &lt;/relationship&gt;
              &lt;relationship&gt;
                &lt;relationship-type-ref&gt;JBOSS_IDENTITY_MEMBERSHIP&lt;/relationship-type-ref&gt;
                &lt;identity-object-type-ref&gt;organization_type&lt;/identity-object-type-ref&gt;
              &lt;/relationship&gt;
            &lt;/relationships&gt;
            &lt;credentials/&gt;
            &lt;attributes/&gt;
            &lt;options&gt;
              &lt;option&gt;
                &lt;name&gt;idAttributeName&lt;/name&gt;
                &lt;value&gt;cn&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;ctxDNs&lt;/name&gt;
                &lt;value&gt;ou=Organization,o=portal,o=gatein,dc=example,dc=com&lt;/value&gt;
              &lt;/option&gt;
              &lt;!--&lt;option&gt;--&gt;
              &lt;!--&lt;name&gt;entrySearchFilter&lt;/name&gt;--&gt;
              &lt;!--&lt;value&gt;&lt;/value&gt;--&gt;
              &lt;!--&lt;/option&gt;--&gt;
              &lt;option&gt;
                &lt;name&gt;allowCreateEntry&lt;/name&gt;
                &lt;value&gt;true&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;parentMembershipAttributeName&lt;/name&gt;
                &lt;value&gt;member&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;isParentMembershipAttributeDN&lt;/name&gt;
                &lt;value&gt;true&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;allowEmptyMemberships&lt;/name&gt;
                &lt;value&gt;true&lt;/value&gt;
              &lt;/option&gt;
              &lt;option&gt;
                &lt;name&gt;createEntryAttributeValues&lt;/name&gt;
                &lt;value&gt;objectClass=top&lt;/value&gt;
                &lt;value&gt;objectClass=groupOfNames&lt;/value&gt;
              &lt;/option&gt;
            &lt;/options&gt;
          &lt;/identity-object-type&gt;
        &lt;/supported-identity-object-types&gt;
        &lt;options&gt;
          &lt;option&gt;
            &lt;name&gt;providerURL&lt;/name&gt;
            &lt;value&gt;ldap://localhost:1389&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;adminDN&lt;/name&gt;
            &lt;value&gt;cn=admin&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;adminPassword&lt;/name&gt;
            &lt;value&gt;admin&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;searchTimeLimit&lt;/name&gt;
            &lt;value&gt;10000&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;createMissingContexts&lt;/name&gt;
            &lt;value&gt;true&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;customJNDIConnectionParameters&lt;/name&gt;
            &lt;value&gt;com.sun.jndi.ldap.connect.pool=true&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;customSystemProperties&lt;/name&gt;
            &lt;value&gt;com.sun.jndi.ldap.connect.pool.maxsize=300000&lt;/value&gt;
            &lt;value&gt;com.sun.jndi.ldap.connect.pool.protocol=plain ssl&lt;/value&gt;
          &lt;/option&gt;
          &lt;option&gt;
            &lt;name&gt;cache.providerRegistryName&lt;/name&gt;
            &lt;value&gt;storeCacheProvider&lt;/value&gt;
          &lt;/option&gt;
        &lt;/options&gt;
      &lt;/identity-store&gt;
    &lt;/identity-stores&gt;
  &lt;/stores&gt;
  &lt;options&gt;
      &lt;option&gt;
         &lt;name&gt;defaultTemplate&lt;/name&gt;
         &lt;value&gt;idm_realm&lt;/value&gt;
      &lt;/option&gt;
  &lt;/options&gt;
&lt;/jboss-identity&gt;
        </programlisting>
      </listitem>
    </itemizedlist>

    <itemizedlist>
      <listitem>
        <para>Change the configuration corresponding to the configuration you
        put when configuring your LDAP server. You have to update the values
        of options <emphasis role="bold">providerURL</emphasis>, <emphasis
        role="bold">adminDN</emphasis>, <emphasis
        role="bold">adminPassword</emphasis> and all instances of <emphasis
        role="bold">ctxDNs</emphasis> according to your LDAP server
        configuration.</para>
      </listitem>
    </itemizedlist>

    <itemizedlist>
      <listitem>
        <para>Delete <emphasis role="bold">exo-tomcat/temp/</emphasis>* to
        have a clean database and then start tomcat.</para>
      </listitem>
    </itemizedlist>

    <para>eXo starts and autocreates its organization model in your directory
    tree. Finally, the structure of the default LDAP schema looks like:</para>

    <mediaobject>
      <imageobject>
        <imagedata fileref="images/organization-exo.jpg" />
      </imageobject>
    </mediaobject>

    <para>That's it! Now eXo uses your LDAP directory as its org model
    storage. Users, groups and memberships are now stored and retrieved from
    there. We suggest that you complete some guideline functions with eXo user
    management portlet and see what it changes in your directory tree.</para>
  </section>

  <section id="Core.LDAPConfiguration.Configuration">
    <title>Configuration</title>

    <para>If you have an existing LDAP server, the eXo predefined settings
    will likely not match your directory structure. eXo LDAP organization
    service implementation was written with flexibility in mind and can
    certainly be configured to meet your requirements.</para>

    <para>The configuration is done in <emphasis
    role="bold">ldap-configuration.xml</emphasis> file, and this section will
    explain the numerous parameters it contains.</para>

    <section id="Core.LDAPConfiguration.Configuration.ConnectionSettings">
      <title>Connection Settings</title>

      <para>Firstly, start by connection settings which will tell eXo how to
      connect to your directory server. These settings are very close to
      <ulink
      url="http://www.oracle.com/technetwork/java/jndi/docs/index.html">JNDI
      API</ulink> context parameters. This configuration is activated by the
      init-param ldap.config of service LDAPServiceImpl.</para>

      <programlisting language="xml">&lt;component&gt;
  &lt;key&gt;org.exoplatform.services.ldap.LDAPService&lt;/key&gt;
  &lt;type&gt;org.exoplatform.services.ldap.impl.LDAPServiceImpl&lt;/type&gt;
  &lt;init-params&gt;
    &lt;object-param&gt;
      &lt;name&gt;ldap.config&lt;/name&gt;
      &lt;description&gt;Default ldap config&lt;/description&gt;
      &lt;object type="org.exoplatform.services.ldap.impl.LDAPConnectionConfig"&gt;
        &lt;field name="providerURL"&gt;&lt;string&gt;ldap://127.0.0.1:389,10.0.0.1:389&lt;/string&gt;&lt;/field&gt;
        &lt;field name="rootdn"&gt;&lt;string&gt;CN=Manager,DC=exoplatform,DC=org&lt;/string&gt;&lt;/field&gt;
        &lt;field name="password"&gt;&lt;string&gt;secret&lt;/string&gt;&lt;/field&gt;
        &lt;!-- field  name="authenticationType"&gt;&lt;string&gt;simple&lt;/string&gt;&lt;/field--&gt;           
        &lt;field name="version"&gt;&lt;string&gt;3&lt;/string&gt;&lt;/field&gt;
        &lt;field  name="referralMode"&gt;&lt;string&gt;follow&lt;/string&gt;&lt;/field&gt;            
        &lt;!-- field  name="serverName"&gt;&lt;string&gt;active.directory&lt;/string&gt;&lt;/field--&gt;
        &lt;field name="minConnection"&gt;&lt;int&gt;5&lt;/int&gt;&lt;/field&gt;
        &lt;field name="maxConnection"&gt;&lt;int&gt;10&lt;/int&gt;&lt;/field&gt;
        &lt;field name="timeout"&gt;&lt;int&gt;50000&lt;/int&gt;&lt;/field&gt;
      &lt;/object&gt;
    &lt;/object-param&gt;
  &lt;/init-params&gt;
&lt;/component&gt;</programlisting>

      <itemizedlist>
        <listitem>
          <para><emphasis role="bold">providerURL</emphasis>: LDAP server URL
          (see <ulink
          url="http://docs.oracle.com/cd/E13211_01/wle/wle50/javadoc/j2ee/jndi/javax/naming/Context.html#PROVIDER_URL">PROVIDER_URL</ulink>).
          For multiple ldap servers, use comma separated list of host:port
          (Ex. ldap://127.0.0.1:389,10.0.0.1:389).</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">rootdn</emphasis>: dn of user that will
          be used by the service to authenticate on the server (see <ulink
          url="http://docs.oracle.com/cd/E13211_01/wle/wle50/javadoc/j2ee/jndi/javax/naming/Context.html#SECURITY_PRINCIPAL">SECURITY_PRINCIPAL</ulink>).</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">password</emphasis>: password for user
          rootdn (see <ulink
          url="http://docs.oracle.com/cd/E13211_01/wle/wle50/javadoc/j2ee/jndi/javax/naming/Context.html#SECURITY_CREDENTIALS">SECURITY_CREDENTIALS</ulink>).</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">authenticationType</emphasis>: type of
          authentication to be used (see <ulink
          url="http://docs.oracle.com/cd/E13211_01/wle/wle50/javadoc/j2ee/jndi/javax/naming/Context.html#SECURITY_AUTHENTICATION">SECURITY_AUTHENTICATION</ulink>).
          Use one of none, simple, strong. Default is simple.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">version</emphasis>: LDAP protocol
          version (see <ulink
          url="http://docs.oracle.com/javase/jndi/tutorial/ldap/misc/version.html">java.naming.ldap.version</ulink>).
          Set to 3 if your server supports LDAP V3.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">referalMode</emphasis>: one of follow,
          ignore,throw (see <ulink
          url="http://docs.oracle.com/cd/E13211_01/wle/wle50/javadoc/j2ee/jndi/javax/naming/Context.html#REFERRAL">REFERRAL</ulink>).</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">serverName</emphasis>: you will need to
          set this to active.directory in order to work with Active Directory
          servers. Any other value will be ignore and the service will act as
          on a standard LDAP.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">maxConnection</emphasis>: the maximum
          number of connections per connection identity that can be maintained
          concurrently.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">minConnection</emphasis>: the number of
          connections per connection identity to create when initially
          creating a connection for the identity.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">timeout</emphasis>: the number of
          milliseconds that an idle connection may remain in the pool without
          being closed and removed from the pool.</para>
        </listitem>
      </itemizedlist>
    </section>

    <section id="Core.LDAPConfiguration.Configuration.OrganizationServiceConfiguration">
      <title>Organization Service Configuration</title>

      <para>Next, you need to configure the eXo <emphasis
      role="bold">OrganizationService</emphasis> to tell him how the directory
      is structured and how to interact with it. This is managed by a couple
      of of init-params : <emphasis role="bold">ldap.userDN.key</emphasis> and
      <emphasis role="bold">ldap.attribute.mapping</emphasis> in file
      <emphasis role="bold">ldap-configuration.xml</emphasis> (by default
      located at portal.war/WEB-INF/conf/organization)</para>

      <programlisting language="xml">&lt;component&gt;
  &lt;key&gt;org.exoplatform.services.organization.OrganizationService&lt;/key&gt;
  &lt;type&gt;org.exoplatform.services.organization.ldap.OrganizationServiceImpl&lt;/type&gt;
  [...]
  &lt;init-params&gt;
    &lt;value-param&gt;
      &lt;name&gt;ldap.userDN.key&lt;/name&gt;
      &lt;description&gt;The key used to compose user DN&lt;/description&gt;
      &lt;value&gt;cn&lt;/value&gt;
    &lt;/value-param&gt;
    &lt;object-param&gt;
      &lt;name&gt;ldap.attribute.mapping&lt;/name&gt;
      &lt;description&gt;ldap attribute mapping&lt;/description&gt;
      &lt;object type="org.exoplatform.services.organization.ldap.LDAPAttributeMapping"&gt;
      [...]
    &lt;/object-param&gt;
  &lt;/init-params&gt;
  [...]
&lt;/component&gt;</programlisting>

      <para><emphasis role="bold">ldap.attribute.mapping</emphasis> maps your
      ldap to eXo. At first there are two main parameters to configure in
      it:</para>

      <programlisting language="xml">&lt;field name="baseURL"&gt;&lt;string&gt;dc=exoplatform,dc=org&lt;/string&gt;&lt;/field&gt;
&lt;field name="ldapDescriptionAttr"&gt;&lt;string&gt;description&lt;/string&gt;&lt;/field&gt;</programlisting>

      <itemizedlist>
        <listitem>
          <para><emphasis role="bold">baseURL</emphasis>: root dn for eXo
          organizational entities. This entry can't be created by eXo and must
          preexist in directory.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">ldapDescriptionAttr</emphasis> (since
          core 2.2+) : Name of a common attribute that will be used as
          description for groups and membership types.</para>
        </listitem>
      </itemizedlist>

      <note>
        <para>(since core 2.2+) : Name of a common attribute that will be used
        as description for groups and membership types.</para>
      </note>

      <para>Other parameters are discussed in the following sections.</para>

      <section id="Core.LDAPConfiguration.Configuration.OrganizationServiceConfiguration.Users">
        <title>Users</title>

        <section id="Core.LDAPConfiguration.Configuration.OrganizationServiceConfiguration.Users.MainParameters">
          <title>Main parameters</title>

          <para>Here are the main parameters to map eXo users to your
          directory :</para>

          <programlisting language="xml">&lt;field name="userURL"&gt;&lt;string&gt;ou=users,ou=portal,dc=exoplatform,dc=org&lt;/string&gt;&lt;/field&gt;
&lt;field name="userObjectClassFilter"&gt;&lt;string&gt;objectClass=person&lt;/string&gt;&lt;/field&gt;
&lt;field name="userLDAPClasses"&gt;&lt;string&gt;top,person,organizationalPerson,inetOrgPerson&lt;/string&gt;&lt;/field&gt;</programlisting>

          <itemizedlist>
            <listitem>
              <para><emphasis role="bold">userURL</emphasis> : base dn for
              users. Users are created in a flat structure under this base
              with a dn of the form: <emphasis
              role="bold">ldap.userDN.key=username,userURL</emphasis></para>
            </listitem>
          </itemizedlist>

          <para>Example :</para>

          <programlisting>uid=john,cn=People,o=MyCompany,c=com</programlisting>

          <para>However, if users exist deeply under userURL, eXo will be able
          to retrieve them.</para>

          <para>Example :</para>

          <programlisting>uid=tom,ou=France,ou=EMEA,cn=People,o=MyCompany,c=com</programlisting>

          <itemizedlist>
            <listitem>
              <para><emphasis role="bold">userObjectClassFilter</emphasis>:
              Filter used under userURL branch to distinguish eXo user entries
              from others.</para>
            </listitem>
          </itemizedlist>

          <para>Example : john and tom will be recognized as valid eXo users
          but EMEA and France entries will be ignored in the following subtree
          :</para>

          <programlisting>uid=john,cn=People,o=MyCompany,c=com
  objectClass: person
  …
ou=EMEA,cn=People,o=MyCompany,c=com
  objectClass: organizationalUnit
  …
    ou=France,ou=EMEA,cn=People,o=MyCompany,c=com
      objectClass: organizationalUnit
      …
        uid=tom,ou=EMEA,cn=People,o=MyCompany,c=com
          objectClass: person
          …</programlisting>

          <itemizedlist>
            <listitem>
              <para><emphasis role="bold">userLDAPClasses</emphasis> : comma
              separated list of classes used for user creation.</para>
            </listitem>
          </itemizedlist>

          <para>When creating a new user, an entry will be created with the
          given objectClass attributes. The classes must at least define cn
          and any attribute refernced in the user mapping.</para>

          <para>Example : Adding the user Marry Simons could produce :</para>

          <programlisting>uid=marry,cn=users,ou=portal,dc=exoplatform,dc=org
  objectclass: top
  objectClass: person
  objectClass: organizationalPerson
  objectClass: inetOrgPerson
  …</programlisting>
        </section>

        <section id="Core.LDAPConfiguration.Configuration.OrganizationServiceConfiguration.Users.UserMapping">
          <title>User mapping</title>

          <para>The following parameters maps ldap attributes to eXo User java
          objects attributes.</para>

          <programlisting language="xml">&lt;field name="userUsernameAttr"&gt;&lt;string&gt;uid&lt;/string&gt;&lt;/field&gt;
&lt;field name="userPassword"&gt;&lt;string&gt;userPassword&lt;/string&gt;&lt;/field&gt;
&lt;field name="userFirstNameAttr"&gt;&lt;string&gt;givenName&lt;/string&gt;&lt;/field&gt;
&lt;field name="userLastNameAttr"&gt;&lt;string&gt;sn&lt;/string&gt;&lt;/field&gt;        
&lt;field name="userDisplayNameAttr"&gt;&lt;string&gt;displayName&lt;/string&gt;&lt;/field&gt;
&lt;field name="userMailAttr"&gt;&lt;string&gt;mail&lt;/string&gt;&lt;/field&gt;</programlisting>

          <itemizedlist>
            <listitem>
              <para><emphasis role="bold">userUsernameAttr</emphasis>:
              username (login)</para>
            </listitem>

            <listitem>
              <para><emphasis role="bold">userPassword</emphasis>: password
              (used when portal authentication is done by eXo login
              module)</para>
            </listitem>

            <listitem>
              <para><emphasis role="bold">userFirstNameAttr</emphasis>:
              firstname</para>
            </listitem>

            <listitem>
              <para><emphasis role="bold">userLastNameAttr</emphasis>:
              lastname</para>
            </listitem>

            <listitem>
              <para><emphasis role="bold">userDisplayNameAttr</emphasis>:
              displayed name</para>
            </listitem>

            <listitem>
              <para><emphasis role="bold">userMailAttr</emphasis>: email
              address</para>
            </listitem>
          </itemizedlist>

          <para>Example : In the previous example, user Marry Simons could
          produce :</para>

          <programlisting>uid=marry,cn=users,ou=portal,dc=exoplatform,dc=org
  objectclass: top
  objectClass: person
  objectClass: organizationalPerson
  objectClass: inetOrgPerson
  …</programlisting>
        </section>
      </section>

      <section id="Core.LDAPConfiguration.Configuration.OrganizationServiceConfiguration.Groups">
        <title>Groups</title>

        <para>eXo groups can be mapped to organizational or applicative groups
        defined in your directory.</para>

        <programlisting language="xml">&lt;field name="groupsURL"&gt;&lt;string&gt;ou=groups,ou=portal,dc=exoplatform,dc=org&lt;/string&gt;&lt;/field&gt;
&lt;field name="groupLDAPClasses"&gt;&lt;string&gt;top,organizationalUnit&lt;/string&gt;&lt;/field&gt;
&lt;field name="groupObjectClassFilter"&gt;&lt;string&gt;objectClass=organizationalUnit&lt;/string&gt;&lt;/field&gt;</programlisting>

        <itemizedlist>
          <listitem>
            <para><emphasis role="bold">groupsURL</emphasis> : base dn for eXo
            groups</para>
          </listitem>
        </itemizedlist>

        <para>Groups can be structured hierarchically under groupsURL.</para>

        <para>Example: Groups communication, communication/marketing and
        communication/press would map to :</para>

        <programlisting>ou=communication,ou=groups,ou=portal,dc=exoplatform,dc=org
…
  ou=marketing,ou=communication,ou=groups,ou=portal,dc=exoplatform,dc=org
  …            
  ou=press,ou=communication,ou=groups,ou=portal,dc=exoplatform,dc=org                          
  …</programlisting>

        <itemizedlist>
          <listitem>
            <para><emphasis role="bold">groupLDAPClasses</emphasis>: comma
            separated list of classes used for group creation.</para>
          </listitem>
        </itemizedlist>

        <para>When creating a new group, an entry will be created with the
        given objectClass attributes. The classes must define at least the
        required attributes: <emphasis role="bold">ou</emphasis>, <emphasis
        role="bold">description</emphasis> and <emphasis
        role="bold">l</emphasis>.</para>

        <note>
          <para>l attribute corresponds to the City property in OU property
          editor</para>
        </note>

        <para>Example : Adding the group human-resources could produce:</para>

        <programlisting>ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
  objectclass: top
  objectClass: organizationalunit
  ou: human-resources
  description: The human resources department
  l: Human Resources
  …</programlisting>

        <itemizedlist>
          <listitem>
            <para><emphasis role="bold">groupObjectClassFilter</emphasis>:
            filter used under groupsURL branch to distinguish eXo groups from
            other entries. You can also use a complex filter if you
            need.</para>
          </listitem>
        </itemizedlist>

        <para>Example : groups WebDesign, WebDesign/Graphists and Sales could
        be retrieved in :</para>

        <programlisting>l=Paris,dc=sites,dc=mycompany,dc=com
  …
  ou=WebDesign,l=Paris,dc=sites,dc=mycompany,dc=com
  …
    ou=Graphists,WebDesign,l=Paris,dc=sites,dc=mycompany,dc=com
    …
l=London,dc=sites,dc=mycompany,dc=com
  …
  ou=Sales,l=London,dc=sites,dc=mycompany,dc=com
  …</programlisting>
      </section>

      <section id="Core.LDAPConfiguration.Configuration.OrganizationServiceConfiguration.MembershipTypes">
        <title>Membership Types</title>

        <para>Membership types are the possible roles that can be assigned to
        users in groups.</para>

        <programlisting language="xml">&lt;field name="membershipTypeURL"&gt;&lt;string&gt;ou=memberships,ou=portal,dc=exoplatform,dc=org&lt;/string&gt;&lt;/field&gt;          
&lt;field name="membershipTypeLDAPClasses"&gt;&lt;string&gt;top,organizationalRole&lt;/string&gt;&lt;/field&gt;
&lt;field name="membershipTypeNameAttr"&gt;&lt;string&gt;cn&lt;/string&gt;&lt;/field&gt;</programlisting>

        <para></para>

        <itemizedlist>
          <listitem>
            <para><emphasis role="bold">membershipTypeURL</emphasis> : base dn
            for membership types storage.</para>
          </listitem>
        </itemizedlist>

        <para>eXo stores membership types in a flat structure under
        membershipTypeURL.</para>

        <para>Example : Roles manager, user, admin and editor could by defined
        by the subtree :</para>

        <programlisting>ou=roles,ou=portal,dc=exoplatform,dc=org
…
  cn=manager,ou=roles,ou=portal,dc=exoplatform,dc=org
  …
  cn=user,ou=roles,ou=portal,dc=exoplatform,dc=org
  …
  cn=admin,ou=roles,ou=portal,dc=exoplatform,dc=org               
  …
  cn=editor,ou=roles,ou=portal,dc=exoplatform,dc=org
  …</programlisting>

        <itemizedlist>
          <listitem>
            <para><emphasis role="bold">membershipTypeLDAPClasses</emphasis>:
            comma separated list of classes for membership types
            creation.</para>
          </listitem>
        </itemizedlist>

        <para>When creating a new membership type, an entry will be created
        with the given objectClass attributes. The classes must define the
        required attributes : <emphasis role="bold">description</emphasis>,
        <emphasis role="bold">cn</emphasis></para>

        <para>Example : Adding membership type validator would produce
        :</para>

        <programlisting>cn=validator,ou=roles,ou=portal,dc=exoplatform,dc=org
  objectclass: top
  objectClass: organizationalRole
  …</programlisting>

        <itemizedlist>
          <listitem>
            <para><emphasis role="bold">membershipTypeNameAttr</emphasis> :
            Attribute that will be used as the name of the role</para>
          </listitem>
        </itemizedlist>

        <para>Example : If membershipTypeNameAttr is 'cn', then role name is
        'manager' for the following membership type entry :</para>

        <programlisting>cn=manager,ou=roles,ou=portal,dc=exoplatform,dc=org</programlisting>
      </section>

      <section id="Core.LDAPConfiguration.Configuration.OrganizationServiceConfiguration.Memberships">
        <title>Memberships</title>

        <para>Memberships are used to assign a role within a group. They are
        entries that are placed under the group entry of their scope group.
        Users in this role are defined as attributes of the membership
        entry.</para>

        <para>Example: To designate tom as the manager of the group
        human-resources:</para>

        <programlisting>ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
  …
  cn=manager,ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
    member: uid=tom,ou=users,ou=portal,dc=exoplatform,dc=org
    …</programlisting>

        <para>The parameters to configure memberships are:</para>

        <programlisting language="xml">&lt;field name="membershipLDAPClasses"&gt;&lt;string&gt;top,groupOfNames&lt;/string&gt;&lt;/field&gt;
&lt;field name="membershipTypeMemberValue"&gt;&lt;string&gt;member&lt;/string&gt;&lt;/field&gt;                              
&lt;field name="membershipTypeRoleNameAttr"&gt;&lt;string&gt;cn&lt;/string&gt;&lt;/field&gt;
&lt;field name="membershipTypeObjectClassFilter"&gt;&lt;string&gt;objectClass=organizationalRole&lt;/string&gt;&lt;/field&gt;</programlisting>

        <itemizedlist>
          <listitem>
            <para><emphasis role="bold">membershipLDAPClasses</emphasis> :
            comma separated list of classes used to create memberships.</para>
          </listitem>
        </itemizedlist>

        <para>When creating a new membership, an entry will be created with
        the given objectClass attributes. The classes must at least define the
        attribute designated by membershipTypeMemberValue.</para>

        <para>Example : Adding membership validator would produce :</para>

        <programlisting>cn=validator,ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
  objectclass: top
  objectClass: groupOfNames
  …</programlisting>

        <para>cn=validator,ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
        objectclass: top objectClass: groupOfNames</para>

        <itemizedlist>
          <listitem>
            <para><emphasis role="bold">membershipTypeMemberValue</emphasis>:
            Multivalued attribute used in memberships to reference users that
            have the role in the group.</para>
          </listitem>
        </itemizedlist>

        <para>Values should be a user dn.</para>

        <para>Example: james and root have admin role within the group
        human-resources, would give:</para>

        <programlisting>cn=admin,ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org
  member: cn=james,ou=users,ou=portal,dc=exoplatform,dc=org
  member: cn=root,ou=users,ou=portal,dc=exoplatform,dc=org
  …</programlisting>

        <itemizedlist>
          <listitem>
            <para><emphasis role="bold">membershipTypeRoleNameAttr</emphasis>:
            Attribute of the membership entry whose value references the
            membership type.</para>
          </listitem>
        </itemizedlist>

        <para>Example : In the following membership entry:</para>

        <para>cn=manager,ou=human-resources,ou=groups,ou=portal,dc=exoplatform,dc=org</para>

        <para>'cn' attribute is used to designate the 'manager' membership
        type. Which could also be said : The name of the role is given by 'cn'
        the attribute.</para>

        <itemizedlist>
          <listitem>
            <para><emphasis
            role="bold">membershipTypeObjectClassFilter</emphasis> : Filter
            used to distinguish membership entries under groups.</para>
          </listitem>
        </itemizedlist>

        <para>You can use rather complex filters.</para>

        <para>Example: Here is a filter we used for a customer that needed to
        trigger a dynlist overlay on openldap.</para>

        <programlisting>(&amp;amp;(objectClass=ExoMembership)(membershipURL=*)) 
</programlisting>

        <para>Note: Pay attention to the xml escaping of the '&amp;' (and)
        operator</para>
      </section>

      <section id="Core.LDAPConfiguration.Configuration.OrganizationServiceConfiguration.UserProfiles">
        <title>User Profiles</title>

        <para>eXo User profiles also have entries in the ldap but the actual
        storage is still done with the hibernate service. You will need the
        following parameters:</para>

        <programlisting language="xml">&lt;field name="profileURL"&gt;&lt;string&gt;ou=profiles,ou=portal,dc=exoplatform,dc=org&lt;/string&gt;&lt;/field&gt;
&lt;field name="profileLDAPClasses"&gt;&lt;string&gt;top,organizationalPerson&lt;/string&gt;&lt;/field&gt;</programlisting>

        <itemizedlist>
          <listitem>
            <para><emphasis role="bold">profileURL</emphasis>: base dn to
            store user profiles</para>
          </listitem>

          <listitem>
            <para><emphasis role="bold">profileLDAPClasses</emphasis>: Classes
            used to when creating user profiles</para>
          </listitem>
        </itemizedlist>
      </section>
    </section>
  </section>

  <section id="Core.LDAPConfiguration.AdvancedTopics">
    <title>Advanced topics</title>

    <section id="Core.LDAPConfiguration.AdvancedTopics.AutomaticDirectoryPopulation">
      <title>Automatic directory population</title>

      <para>At startup, eXo can populate the organization model based
      on</para>

      <para>eXo organizational model has User,Group,Membership and Profile
      entities. For each, we define a base dn that should be below baseURL. At
      startup, if one of userURL, groupsURL, membershipTypeURL or profileURL
      does not exist fully, eXo will attempt to create the missing subtree by
      parsing the dn and creating entries on-the-fly. To determine the classes
      of the created entries, the following rules are applied :</para>

      <itemizedlist>
        <listitem>
          <para>ou=... : objectClass=top,objectClass=organizationalUnit</para>
        </listitem>

        <listitem>
          <para>cn=... : objectClass=top,objectClass=organizationalRole</para>
        </listitem>

        <listitem>
          <para>c=... : objectClass=country</para>
        </listitem>

        <listitem>
          <para>o=... : objectClass=organization</para>
        </listitem>

        <listitem>
          <para>dc=.. :
          objectClass=top,objectClass=dcObject,objectClass=organization</para>
        </listitem>
      </itemizedlist>

      <para>Example:</para>

      <para>If baseURL is <emphasis role="bold">o=MyCompany,c=com</emphasis>
      and groupsURL is <emphasis
      role="bold">dc=groups,cn=Extranet,c=France,ou=EMEA,o=MyCompany,c=com</emphasis>
      then, the following subtree will be created :</para>

      <programlisting>ou=EMEA,o=MyCompany,c=com
  objectClass: top
  objectClass: organizationalUnit
  …
    c=France,ou=EMEA,o=MyCompany,c=com
      objectClass: top
      objectClass: country
      …
      cn=Extranet,c=France,ou=EMEA,o=MyCompany,c=com
        objectClass: top
        objectClass: organizationalRole
        …
        dc=groups,cn=Extranet,c=France,ou=EMEA,o=MyCompany,c=com
          objectClass: top
          objectClass: dcObject
          objectClass: organization            
          …</programlisting>
    </section>

    <section id="Core.LDAPConfiguration.AdvancedTopics.ActiveDirectorySampleConfiguration">
      <title>Active Directory sample configuration</title>

      <para>Here is an alternative configuration for active directory that you
      can find in <emphasis
      role="bold">activedirectory-configuration.xml</emphasis></para>

      <note>
        <para>There is a microsoft limitation: password can't be set in AD via
        unsecured connection you have to use the ldaps protocol</para>
      </note>

      <para>here is how to use LDAPS protocol with Active Directory :</para>

      <programlisting>1 setup AD to use SSL:

    * add Active Directory Certificate Services role
    * install right certificate for DC machine

2 enable Java VM to use certificate from AD (note that this step is not AD related, it is applicable for any LDAP server when we want to enable the ssl protocol):

    * import root CA used in AD, to keystore, something like

      keytool -importcert -file 2008.cer -keypass changeit -keystore /home/user/java/jdk1.6/jre/lib/security/cacerts

    * set java options

      JAVA_OPTS="${JAVA_OPTS} -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStore=/home/user/java/jdk1.6/jre/lib/security/cacerts"</programlisting>

      <programlisting language="xml">[...]
  &lt;component&gt;
  &lt;key&gt;org.exoplatform.services.ldap.LDAPService&lt;/key&gt;
[..]
       &lt;object type="org.exoplatform.services.ldap.impl.LDAPConnectionConfig"&gt;         
         &lt;!-- for multiple ldap servers, use comma seperated list of host:port (Ex. ldap://127.0.0.1:389,10.0.0.1:389) --&gt;
         &lt;!-- whether or not to enable ssl, if ssl is used ensure that the javax.net.ssl.keyStore &amp; java.net.ssl.keyStorePassword properties are set --&gt;
         &lt;!-- ldap service will check protocol, if protocol is ldaps, ssl is enable (Ex. for enable ssl: ldaps://10.0.0.3:636 ;for disable ssl: ldap://10.0.0.3:389 ) --&gt;
         &lt;!-- when enable ssl, ensure server name is *.directory and port (Ex. active.directory) --&gt;        
         &lt;field  name="providerURL"&gt;&lt;string&gt;ldaps://10.0.0.3:636&lt;/string&gt;&lt;/field&gt;
         &lt;field  name="rootdn"&gt;&lt;string&gt;CN=Administrator,CN=Users, DC=exoplatform,DC=org&lt;/string&gt;&lt;/field&gt;
         &lt;field  name="password"&gt;&lt;string&gt;site&lt;/string&gt;&lt;/field&gt;      
         &lt;field  name="version"&gt;&lt;string&gt;3&lt;/string&gt;&lt;/field&gt;             
         &lt;field  name="referralMode"&gt;&lt;string&gt;ignore&lt;/string&gt;&lt;/field&gt;                      
         &lt;field  name="serverName"&gt;&lt;string&gt;active.directory&lt;/string&gt;&lt;/field&gt;                  
       &lt;/object&gt;
[..]
  &lt;component&gt;
    &lt;key&gt;org.exoplatform.services.organization.OrganizationService&lt;/key&gt;
    [...]
        &lt;object type="org.exoplatform.services.organization.ldap.LDAPAttributeMapping"&gt;                
          [...]
          &lt;field  name="userLDAPClasses"&gt;&lt;string&gt;top,person,organizationalPerson,user&lt;/string&gt;&lt;/field&gt;
          &lt;field  name="userObjectClassFilter"&gt;&lt;string&gt;objectClass=user&lt;/string&gt;&lt;/field&gt;
          &lt;field  name="userAuthenticationAttr"&gt;&lt;string&gt;mail&lt;/string&gt;&lt;/field&gt;
          &lt;field  name="userUsernameAttr"&gt;&lt;string&gt;sAMAccountName&lt;/string&gt;&lt;/field&gt;
          &lt;field  name="userPassword"&gt;&lt;string&gt;unicodePwd&lt;/string&gt;&lt;/field&gt; 
          &lt;field  name="userLastNameAttr"&gt;&lt;string&gt;sn&lt;/string&gt;&lt;/field&gt;
          &lt;field  name="userDisplayNameAttr"&gt;&lt;string&gt;displayName&lt;/string&gt;&lt;/field&gt;
          &lt;field  name="userMailAttr"&gt;&lt;string&gt;mail&lt;/string&gt;&lt;/field&gt;
          [..]
          &lt;field  name="membershipTypeLDAPClasses"&gt;&lt;string&gt;top,group&lt;/string&gt;&lt;/field&gt;
          &lt;field  name="membershipTypeObjectClassFilter"&gt;&lt;string&gt;objectClass=group&lt;/string&gt;&lt;/field&gt;
          [..]
          &lt;field  name="membershipLDAPClasses"&gt;&lt;string&gt;top,group&lt;/string&gt;&lt;/field&gt;
          &lt;field  name="membershipObjectClassFilter"&gt;&lt;string&gt;objectClass=group&lt;/string&gt;&lt;/field&gt;
        &lt;/object&gt;
        [...]  
&lt;/component&gt;  </programlisting>
    </section>

    <section id="Core.LDAPConfiguration.AdvancedTopics.OpenLDAPDynlistOverlays">
      <title>OpenLDAP dynlist overlays</title>

      <para>If you use OpenLDAP, you may want to use the <ulink
      url="http://www.openldap.org/faq/data/cache/1169.html">overlays</ulink>.
      Here is how you can use the <ulink
      url="http://www.openldap.org/faq/data/cache/1209.html">dynlist
      overlay</ulink> to have memberships dynamically populated.</para>

      <para>The main idea is to have your memberships populated dynamically by
      an ldap query. Thus, you no longer have to maintain manually the roles
      on users.</para>

      <para>To configure the dynlist, add the following to your <emphasis
      role="bold">slapd.conf</emphasis> :</para>

      <programlisting>dynlist-attrset         ExoMembership membershipURL member</programlisting>

      <para>This snipet means : On entries that have ExoMembership class, use
      the URL defined in the value of attribute membershipURL as a query and
      populate results under the multivalues attribute member.</para>

      <para>Now let's declare the corresponding schema (replace XXXXX to adapt
      to your own IANA code):</para>

      <programlisting>attributeType ( 1.3.6.1.4.1.XXXXX.1.59 NAME 'membershipURL' SUP memberURL )</programlisting>

      <para>membershipURL inherits from memberURL.</para>

      <programlisting>objectClass ( 1.3.6.1.4.1.XXXXX.2.12  NAME 'ExoMembership' SUP top MUST ( cn ) MAY (membershipURL $ member $ description ) )</programlisting>

      <para>ExoMembership must define cn and can have attributes :</para>

      <itemizedlist>
        <listitem>
          <para>membershipURL: trigger for the dynlist</para>
        </listitem>

        <listitem>
          <para>member : attribute populated by the dynlist</para>
        </listitem>

        <listitem>
          <para>description : used by eXo for display</para>
        </listitem>
      </itemizedlist>

      <programlisting># the TestGroup group
dn: ou=testgroup,ou=groups,ou=portal,o=MyCompany,c=com
objectClass: top
objectClass: organizationalUnit
ou: testgroup
l: TestGroup
description: the Test Group</programlisting>

      <para>On this group, we can bind an eXo membership where the overlay
      will occur:</para>

      <programlisting># the manager membership on group TestGroup
dn: cn=manager, ou=TestGroup,ou=groups,ou=portal,o=MyCompany,c=com
objectClass: top
objectClass: ExoMembership
membershipURL: ldap:///ou=users,ou=portal,o=MyCompany,c=com??sub?(uid=*)
cn: manager</programlisting>

      <para>This dynlist assigns the role <emphasis
      role="bold">manager:/testgroup</emphasis> to any user.</para>
    </section>

    <section>
      <title>Disable/Enable an User</title>

      <para>To be able to disable or enable an user account which is supported
      since JCR 1.16, you will need to do additional steps according to your
      LDAP server.</para>

      <para>In case of AD, you have nothing to do, it will be enabled
      automatically as the ability to enable/disable an user account is
      supported natively in AD. We rely on the special attribute
      <emphasis>userAccountControl</emphasis>. In the
      <emphasis>LDAPAttributeMapping</emphasis> make sure that the field
      <emphasis>userLDAPClasses</emphasis> is configured to
      <emphasis>top,person,organizationalPerson,user</emphasis> or any object
      class that includes the attribute
      <emphasis>userAccountControl</emphasis>.</para>

      <para>For all other LDAP servers, you will need to define the attribute
      <emphasis>userAccountControl</emphasis>, to do so you can either (if
      allowed by your LDAP server) modify the object class
      <emphasis>inetOrgPerson</emphasis> in order to add the attribute
      <emphasis>userAccountControl</emphasis> or define a new object class on
      top of <emphasis>inetOrgPerson</emphasis> that includes the attribute
      <emphasis>userAccountControl</emphasis>.</para>

      <para>See below the definition of the attribute
      <emphasis>userAccountControl</emphasis> which is needed in both cases
      and the definition of the object class <emphasis>user</emphasis> that is
      needed only for the second case in a schema format.</para>

      <programlisting># ldap-disabled-accounts.schema -- Disabled Account Schema
#   This schema is an extension required in case we would like
#   to be able to support enabled and disabled account

attributetype ( 1.2.840.113556.1.4.8
 NAME 'userAccountControl'
 DESC 'Flags that control the behavior of the user account'
 EQUALITY integerMatch
 SYNTAX '1.3.6.1.4.1.1466.115.121.1.27'
 SINGLE-VALUE )

objectclass ( 1.2.840.113556.1.5.9
 NAME 'user'
 SUP inetOrgPerson
 STRUCTURAL 
 MAY (userAccountControl) )</programlisting>

      <para>In case you would need an ldif instead of a schema, it would be
      something like that</para>

      <programlisting>dn: cn=schema
changetype: modify
add: attributeTypes
attributeTypes: ( 1.2.840.113556.1.4.8 
 NAME 'userAccountControl' 
 DESC 'Flags that control the behavior of the user account' 
 EQUALITY integerMatch 
 SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' 
 SINGLE-VALUE )

dn: cn=schema
changetype: modify
add: objectClasses
objectClasses: ( 1.2.840.113556.1.5.9 
 NAME 'user' 
 SUP inetOrgPerson 
 STRUCTURAL 
 MAY (userAccountControl) )</programlisting>

      <para>Once you have defined the new attribute
      <emphasis>userAccountControl</emphasis> in your LDAP server, you will
      need to configure it in the <emphasis>LDAPAttributeMapping</emphasis> to
      enable the ability to enable/disable an user, by adding a new field as
      next:</para>

      <programlisting>&lt;field name="userAccountControlAttr"&gt;&lt;string&gt;userAccountControl&lt;/string&gt;&lt;/field&gt;</programlisting>

      <para>In case you decided to define also the
      <emphasis>objectclass</emphasis> <emphasis>user</emphasis>, you will
      also need to modify the value of the field
      <emphasis>userLDAPClasses</emphasis> as next:</para>

      <programlisting>&lt;field name="userLDAPClasses"&gt;&lt;string&gt;top,person,organizationalPerson,inetOrgPerson,user&lt;/string&gt;&lt;/field&gt;</programlisting>

      <para>Once these steps done you will be able to enable/disable an user
      account thanks to the method
      <emphasis>UserHandler.setEnabled</emphasis>, in case old structure is
      detected it will automatically try to migrate to the new user object
      class.</para>
    </section>
  </section>
</section>
