LDAP User Attribute Sources

uPortal is capable of retrieving user attributes from an LDAP source. To configure this behavior, you'll need to do the following.

Step 1: Configure Ldap Settings

Option #1: Add ldap details in your properties file (version uPortal 4.0.9+)

Since uPortal 4.0.9, users can specify their ldap details in the properties file below (filters/local.properties). This feature comes in handy if you have multiple environments (development, test, production, etc..). You can create a properties file for each environment (i.e, dev.properties) and build uPortal with the specified properties file (ant clean deploy-war -Denv=dev). Without the -Denv parameter the local.properties file will be used by default. 

  • Open your properties file (i.e., filters/local.properties)
  • Add your ldap server information below

filters/local.properties
# LDAP server connection settings (optional)
# To connect to LDAP, provide your connection information here and uncomment one 
# or both integration beans in uportal-war/src/main/resources/properties/contexts/ldapContext.xml
environment.build.ldap.url=
environment.build.ldap.baseDn=
environment.build.ldap.userName=
environment.build.ldap.password=

Option #2: Edit the ldapContext.xml file

  • Open uportal-war/src/main/resources/properties/contexts/ldapContext.xml
  • Add your ldap server information in the defaultLdapContext_target bean (see below)
  • NOTE: Based on feedback, some users have found that the baseDN property was required to setup their configuration. 

uportal-war/src/main/resources/properties/contexts/ldapContext.xml
 
<bean id="defaultLdapContext_target" class="org.springframework.ldap.core.support.LdapContextSource">
        <property name="url" value="${ldap.url}"/>
        <property name="base" value="${ldap.baseDn}"/>
        <property name="userDn" value="${ldap.userName}"/>
        <property name="password" value="${ldap.password}"/>
        <property name="pooled" value="true"/>
</bean>

uPortal 4.0.3: If you are receiving the following error (

Error rendering macro 'jira' : Unable to locate Jira server for this macro. It may be due to Application Link configuration.
)

[org.springframework.ldap.core.support.LdapContextSource]: Bean property 'userName' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

Replace the property name, userName, in the defaultLdapContext bean above with userDn.

 

  • If you are configuring your LDAP context to connect to Active Directory, you may need to add the following properties to the bean definition:

uportal-war/src/main/resources/properties/contexts/ldapContext.xml
 <property name="baseEnvironmentProperties">
      <map>
        <entry>
          <key>
            <value>java.naming.security.authentication</value>
          </key>
          <value>simple</value>
        </entry>
        <entry key="java.naming.referral">
          <value>follow</value>
        </entry>
      </map>
 </property>

Step 2: Add an LDAP Attribute source

  • Open uportal-war/src/main/resources/properties/contexts/personDirectoryContext.xml

  • Edit the mergedPersonAttributeDao bean definition to add uPortalLdapAttributeSource under personAttributeDaos:

    uportal-war/src/main/resources/properties/contexts/personDirectoryContext.xml
      <bean id="mergedPersonAttributeDao"
    class="org.jasig.services.persondir.support.CachingPersonAttributeDaoImpl">
          <property name="usernameAttributeProvider" ref="usernameAttributeProvider" />
          <property name="cacheNullResults" value="true" />
          <property name="userInfoCache">
              <bean class="org.jasig.portal.utils.cache.MapCacheFactoryBean">
                  <property name="cacheFactory" ref="cacheFactory" />
                  <property name="cacheName" value="org.jasig.services.persondir.USER_INFO.merged" />
              </bean>
          </property>
          <property name="cacheKeyGenerator" ref="userAttributeCacheKeyGenerator" />
          <property name="cachedPersonAttributesDao" >
              <bean class="org.jasig.services.persondir.support.MergingPersonAttributeDaoImpl">
                  <property name="merger">
                      <!-- This is a "first one wins" strategy. I.e. the first value found for
                      any given result attribute will be assigned to the user. Different values
                      found in subsequently queried attribute sources will be ignored. Suitable
                      if uP-local attributes should always take precedence. Other
                      options (all in the same package):
    
                          MultivaluedAttributeMerger - Collects values from all DAOs into lists (does not
                            filter out duplicate values, though)
                          ReplacingAttributeAdder - "Last one wins" strategy. I.e. the opposite of
                            NoncollidingAttributeAdder.
                      -->
                      <bean class="org.jasig.services.persondir.support.merger.NoncollidingAttributeAdder" />
                  </property>
                  <property name="usernameAttributeProvider" ref="usernameAttributeProvider" />
                  <property name="personAttributeDaos">
                      <list>
                          <!-- Provides a single attribute (but only for the current logged in user):  impersonating='true'|'false' -->
                          <bean class="org.jasig.portal.persondir.ImpersonationStatusPersonAttributeDao" />
                          <bean class="org.jasig.services.persondir.support.CascadingPersonAttributeDao">
                              <property name="usernameAttributeProvider" ref="usernameAttributeProvider" />
                              <property name="personAttributeDaos">
                                  <list>
                                      <ref bean="uPortalAccountUserSource" />
                                      <ref bean="uPortalJdbcUserSource" />
                                  </list>
                              </property>
                          </bean>
                          <!-- ADDITIONAL ATTRIBUTE SOURCES GET ADDED HERE
    
                          Don't add more sources to the CascadingPersonAttributeDao.personAttributeDaos
                          list above unless you're adding "special" DAOs tasked with augmenting/transforming
                          the attributes generated by uP-local DAOs. (CascadingPersonAttributeDao takes
                          the results from the first-DAO, transforms them into a query, and passes that
                          query to each subsequent DAO. I.e. subsequent DAOs in the cascade list will
                          *not* be given a chance to process the original query. But they will if you add
                          them directly to the MergingPersonAttributeDaoImpl.personAttributeDaos list here.)
                          -->
                          <!-- Add your LDAP Attribute source here.  <ref bean="uPortalLdapAttributeSource"/> -->
                      </list>
                  </property>
              </bean>
          </property>
      </bean>
    
  • Next, add the LDAP attribute source bean definition to the same file. This is where you put your baseDN.

     

    uportal-war/src/main/resources/properties/contexts/personDirectoryContext.xml
        <!-- Where non-local attribute DAOs go -->
        <!-- Enter the mapping between 'internal' names (keys) and set of one or more LDAP attribute names (values). -->
        <bean id="uPortalLdapAttributeSource" class="org.jasig.services.persondir.support.ldap.LdapPersonAttributeDao">
            <property name="contextSource" ref="defaultLdapContext" />
     
            <!--  Enter all keys that you want users to search with in the Directory Search portlet or portal
                  search capability. This should contain values from list directoryQueryAttributes in properties/contexts/userContext.xml.
    	      Key is internal name, value is ldap attribute name.
            -->
     	<property name="queryAttributeMapping">
    		<map>
    			  <entry key="username" value="uid" /><!-- should match the uid attribute in your directory;  e.g. sAMAccountName for Active Directory. -->
    			  <entry key="cn"  value="cn" />
    			  <entry key="givenName" value="givenName"/>
                              <entry key="sn" value="sn" />
    			  <entry key="mail" value="mail" />
    	      	</map>
            </property>
            <property name="queryType" value="OR"/>
            <!-- key is ldap attribute name, values are internal names. -->
    		<property name="resultAttributeMapping">
                     <map>
                            <entry key="eduPersonPrimaryAffiliation">
                                <value>uPortalTemplateUserName</value>
                            </entry>
                            <entry key="eduPersonAffiliation">
                                <value>eduPersonAffiliation</value>
                            </entry>
                            <entry key="eduPersonNickname">
                                <set>
                                    <value>eduPersonNickname</value>
                                    <value>user.name.nickName</value>
                                </set>
                            </entry>
                            <entry key="eduPersonOrgDN">
                                <set>
                                    <value>eduPersonOrgDN</value>
                                    <value>user.employer</value>
                                </set>
                            </entry>
                            <entry key="eduPersonOrgUnitDN">
                                <set>
                                    <value>eduPersonOrgUnitDN</value>
                                    <value>user.department</value>
                                </set>
                            </entry>
                            <entry key="eduPersonPrimaryAffiliation">
                                <value>eduPersonPrimaryAffiliation</value>
                            </entry>
                            <entry key="eduPersonPrincipalName">
                                <value>eduPersonPrincipalName</value>
                            </entry>
                            <entry key="c">
                                <value>c</value>
                            </entry>
                            <entry key="cn">
                                <value>cn</value>
                            </entry>
                            <entry key="description">
                                <value>description</value>
                            </entry>
                            <entry key="displayName">
                                <value>displayName</value>
                            </entry>
                            <entry key="facsimileTelephoneNumber">
                                <value>facsimileTelephoneNumber</value>
                            </entry>
                            <entry key="givenName">
                                <set>
                                    <value>givenName</value>
                                    <value>user.name.given</value>
                                </set>
                            </entry>
                            <entry key="homePhone">
                                <value>homePhone</value>
                            </entry>
                            <entry key="homePostalAddress">
                                <value>homePostalAddress</value>
                            </entry>
                            <entry key="initials">
                                <value>initials</value>
                            </entry>
                            <entry key="jpegPhoto">
                                <value>jpegPhoto</value>
                            </entry>
                            <entry key="l">
                                <value>l</value>
                            </entry>
                            <entry key="labeledURI">
                                <value>labeledURI</value>
                            </entry>
                            <entry key="mail">
                                <set>
                                    <value>mail</value>
                                    <value>user.home-info.online.email</value>
                                </set>
                            </entry>
                            <entry key="mobile">
                                <value>mobile</value>
                            </entry>
                            <entry key="o">
                                <value>o</value>
                            </entry>
                            <entry key="ou">
                                <value>ou</value>
                            </entry>
                            <entry key="pager">
                                <value>pager</value>
                            </entry>
                            <entry key="postalAddress">
                                <value>postalAddress</value>
                            </entry>
                            <entry key="postalCode">
                                <value>postalCode</value>
                            </entry>
                            <entry key="postOfficeBox">
                                <value>postOfficeBox</value>
                            </entry>
                            <entry key="preferredLanguage">
                                <value>preferredLanguage</value>
                            </entry>
                            <entry key="seeAlso">
                                <value>seeAlso</value>
                            </entry>
                            <entry key="sn">
                                <set>
                                    <value>sn</value>
                                    <value>user.name.family</value>
                                </set>
                            </entry>
                            <entry key="st">
                                <value>st</value>
                            </entry>
                            <entry key="street">
                                <value>street</value>
                            </entry>
                            <entry key="telephoneNumber">
                                <value>telephoneNumber</value>
                            </entry>
                            <entry key="uid">
    							<set>
    								<value>uid</value>
    	                            <value>username</value> <!-- UP-4185 populate username in case user hasn't logged in yet -->
    	                            <value>user.login.id</value>  <!-- UP-4177 LDAP needs to fill in user.login.id -->
    							</set>
    						</entry>
                            <entry key="userCertificate">
                                <value>userCertificate</value>
                            </entry>
                            <entry key="userSMIMECertificate">
                                <value>userSMIMECertificate</value>
                            </entry>
                </map>
            </property>
    	</bean>
    
  • You may need to update the available attributes and query to match your server. Connections to Active Directory servers will most likely use a query of "(sAMAccountName={0})" which is handled by entry username of queryAttributeMapping mapping to sAMAccountName.
  • Note: The above querryAttributeMapping map keys need corresponding changes to uportal-war/src/main/resources/properties/contexts/userContext.xml for the Directory Search Portlet to find the values in the LDAP source. See example below:

     

    uportal-war/src/main/resources/properties/contexts/userContext.xml
      <!-- The following attribute names are used in searching for users through 
             person-directory, such as from within the Directory framework portlet. These should correspond to
             the internal names (keys, not the ldap attribute names) of the queryAttributeMapping property of
             bean uPortalLdapAttributeSource in personDirectoryContext.xml. -->
        <util:list id="directoryQueryAttributes">
            <value>givenName</value>
            <value>sn</value>
            <value>cn</value>
            <value>mail</value>
            <value>username</value>
        </util:list>


       

Step 3: Rebuild/Redeploy uPortal

From the root of your uPortal source:

ant clean deploy-war

Step 4: Restart uPortal

Restart your tomcat server after deploying your modifications

Additional References

uPortal mailing list Q&A related topic
     Q. Is there a way to use an attribute returned from an LdapPersonAttributeDao as the matching value for a SingleRowJdbcPersonAttributeDao?
     A. It does support this. Swap out the MergingPersonAttributeDao with the CascadingPersonAttributeDao and the results of child bean A get added to the query map for the next bean in the list.
         There are several examples here: https://mywebspace.wisc.edu/dalquist/web/JA-SIG/UWExamples/personDirectoryContext.xml

Having problems with these instructions?

Please send us feedback at uportal-user@lists.ja-sig.org