JIRA
Install
Admin
Use
Search JIRA documentation:

LDAP Integration

PDF
PDF

Many organisations have an LDAP directory acting as a centralised database of system users. JIRA is able to authenticate users against their LDAP password.

About JIRA's LDAP Integration

In JIRA, user management is handled by OSUser, a pluggable user management framework. OSUser is configured through the WEB-INF/classes/osuser.xml file.

Only password-checking for LDAP users is done in JIRA

The main point to realise is that user profiles are still managed in JIRA (the OFBizProfileProvider in osuser.xml). Only the password lookup is done against LDAP, and only if the JIRA username coincides with a LDAP username.

Technically, this behaviour is due to Credentials (password) checking being a separate operation to user-profile lookups. The profile can be loaded from the JIRA database, but the password looked up from LDAP. Furthermore, multiple credentials providers can be specified (here, LDAP and OSUser), and if one fails, the other will be used. This allows non-LDAP users to log in with their JIRA password.

Not all LDAP users have JIRA access

Another effect of this implementation is that LDAP users do not automatically have access to JIRA. A JIRA account must be created for each user wishing to use JIRA. You can bulk-create users from LDAP with this LDAP user importer.

This is because each JIRA user has a set of groups (for example, 'jira-users') stored in their profile. Without an associated group, that user can do nothing; not even browse JIRA (they lack the 'use' permission).

Thus, for an LDAP user to be able to use JIRA, a JIRA administrator must create an account for them, and assign them to a group (typically 'jira-user'). The password in this JIRA account will be ignored, as the LDAP password will override it.

Planned Improvements

In future, we plan to more tightly integrate LDAP into JIRA, so that LDAP groups can be mapped to JIRA groups, and user management can be fully externalised (see Plans for JIRA's LDAP integration). We'd like feedback as we go further with this; please see this issue report for current status, and add your use-case as a comment. Thanks!

Atlassian Crowd

Atlassian Crowd is Atlassian's single sign-on product. Crowd provides an interface for managing users and groups, and provides an OSUser implementation that allows JIRA to fully delegate users and groups to Crowd, and hence LDAP. Thus while we still plan to develop tighter JIRA-LDAP integration, purchasers of Crowd can achieve this right now by using Crowd as an intermediary. See Crowd's JIRA integration documentation for details.

Step 1. Configuring LDAP Integration

JIRA Enterprise Edition

JIRA Enterprise contains a configuration utility which lets you auto-generate a valid osuser.xml file. This can be accessed from Admin -> System -> LDAP:

LDAP Configurer in JIRA Enterprise

JIRA Professional & Standard Editions

In JIRA Professional and JIRA Standard, LDAP integration is configured by manually editing the WEB-INF/classes/osuser.xml file.

In the JIRA Standalone distribution, this file can be edited directly in atlassian-jira/WEB-INF/classes/osuser.xml. In the WAR/webapp distribution, it should be copied from webapp/WEB-INF/classes/osuser.xml to edit-webapp/WEB-INF/classes/, edited there, and then rebuilt into an updated .war file with the 'ant war' command.

The default osuser.xml contains:

<opensymphony-user>
  <authenticator
      class="com.opensymphony.user.authenticator.SmartAuthenticator" />

  <provider
      class="com.atlassian.core.ofbiz.osuser.CoreOFBizCredentialsProvider">
      <property name="exclusive-access">true</property>
  </provider>

  <provider
      class="com.opensymphony.user.provider.ofbiz.OFBizProfileProvider">
    <property name="exclusive-access">true</property>
  </provider>

  <provider
      class="com.opensymphony.user.provider.ofbiz.OFBizAccessProvider">
    <property name="exclusive-access">true</property>
  </provider>

</opensymphony-user>

CredentialsProviders are responsible for checking usernames and passwords, which is what we are interested in here. The default CoreOFBizCredentialsProvider looks in the JIRA database. We are going to add a LDAPCredentialsProvider, so that LDAP users can also be authenticated:

<opensymphony-user>
  <authenticator class="com.opensymphony.user.authenticator.SmartAuthenticator" />

<provider
      class="com.opensymphony.user.provider.ldap.LDAPCredentialsProvider">
 <property name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</property>
 <property name="java.naming.provider.url">ldap://localhost:389</property>
 <property name="searchBase">dc=atlassian,dc=com</property>
 <property name="uidSearchName">uid</property>
 <!--
 <property name="java.naming.security.principal">cn=Manager,dc=atlassian,dc=com</property>
 <property name="java.naming.security.credentials">secret</property>
 <property name="exclusive-access">true</property>
-->
</provider>

<provider class="com.atlassian.core.ofbiz.osuser.CoreOFBizCredentialsProvider">
  <property name="exclusive-access">true</property>
</provider>

<provider class="com.opensymphony.user.provider.ofbiz.OFBizProfileProvider">
  <property name="exclusive-access">true</property>
</provider>

<provider class="com.opensymphony.user.provider.ofbiz.OFBizAccessProvider">
  <property name="exclusive-access">true</property>
</provider>

</opensymphony-user>

It is necessary to use both the LDAP and OFBiz providers, and the order must be as shown (LDAP first).

Some LDAP properties that are commonly set here are:

PropertyRequiredDescriptionExample
java.naming.factory.initial Yes Specifies that JNDI (the directory API) should use the LDAP implementation Should always be com.sun.jndi.ldap.LdapCtxFactory
java.naming.provider.urlYesLDAP URL of your server ldap://localhost:389
searchBaseYesThe node in the LDAP tree to search below for usernames. The root LDAP node is typically called 'dc=companyname,dc=com', and user account nodes are usually stored in a subtree, like 'cn=Users,dc=companyname,dc=com'.
uidSearchNameYesAttribute expected to contain username Typically uid, or sAMAccountName for MS ActiveDirectory.
java.naming.security.principalNoUsername to initially log in to LDAP as. Not required if anonymous user lookups are allowed. Eg. 'cn=Administrator,cn=Users,dc=companyname,dc=com'
java.naming.security.credentialsNoPassword for initial login. Not required if anonymous lookups are allowed.
providerNameNo unique name for this LDAP provider. Useful when you specify multiple LDAP providers (allowing fallback), and need to distinguish them in the debug logs.
cacheTimeoutNoThe value in milliseconds for duration of password caching. Password caching reduces the load JIRA will put on the LDAP server. Only successful authentication attempts are cached. The default value is 30 minutes (1,800,000 ms). 0 (to disable caching)

The full list of properties is specified in the JNDI documentation.

Once you have made this modification and restarted JIRA, JIRA users whose username also exists in LDAP will be authenticated against their LDAP password.

Step 2. Disabling JIRA's Password Management

Once you have LDAP-based password checking working, you should go to Admin -> General Configuration, and turn on External password management (see Configuring JIRA documentation). This will disable the "change my password" links in the JIRA interface, ensuring that passwords are now only managed via LDAP.

Configuration Notes

LDAP over SSL

With plain LDAP, passwords may be passing over the network unencrypted, which (depending on your network security) may be a security problem. If you wish to connect to LDAP over SSL, see the Connecting to SSL services guide for details on how to import the SSL server's public key. In osuser.xml, you would need to use ldaps:// in the URL if you have port 636 dedicated to LDAP over SSL.

Multiple LDAP trees (eg. ActiveDirectory domains)

If you wish to authenticate users from multiple LDAP directories or different trees in the same directory, simply edit the OSUser file and add a LDAPCredentialsProvider section for each (see 'Configuring LDAP Integration' above). JIRA will query them in order, and the first one containing the requested user will be used for password checking. As soon as a user is found, the password is checked and no further processing is done (ie. only one password will work).

If you have more than one LDAPCredentialsProvider it is a good idea to give each a unique providerName attribute for debugging purposes.

ActiveDirectory users note: a better approach to searching multiple trees is to set up an Active Directory Global Catalog. This is an AD instance which mirrors records in other instances. Searching the Global Catalog is thus equivalent to searching all mirrored LDAP directories. This is faster and more reliable than JIRA's LDAP fallback.

If you have a Global Catalog set up, it can be searched via LDAP on port 3268 (eg. ldap://adserver:3268) or 3269 for SSL (eg. ldaps://adserver:3269). See this guide for more information.

LDAP on Linux

See these notes on how to set up a LDAP directory on a Linux server for use with JIRA.

Debugging

Cannot create osuser.xml file via JIRA LDAP Configurer

To see exactly why the JIRA LDAP Configurer is failing, follow these steps:

  1. Log in as a user with the 'JIRA System Administrators' global permission.
  2. Bring up the administration page by clicking either the 'Administration' link on the top bar or the title of the Administration box on the dashboard.

  3. Under the 'System' sub-menu in the left-hand navigation column, click the 'Logging & Profiling' link.
  4. The 'Logging & Profiling' page will display. Click the 'Edit' link next to 'com.atlassian.jira.web.action.util.LDAPConfigurer'
  5. Change the logging level to 'DEBUG', then click 'Update'. This temporarily turns up logging for the JIRA LDAP Configurer.
  6. When you next try to submit your LDAP server details via the JIRA LDAP Configurer, you should see extra logs on stdout.

Cannot authenticate against LDAP password

If JIRA does not authenticate against the LDAP password, then something is probably wrong with your setup. First, ensure that the user you are trying to connect as has a JIRA account (see above). Make sure you have the LDAP connection details correct (basename, uid, username/password). These details are best discovered with the help of an LDAP browser such as Apache Directory Studio or JXplorer.

To see exactly why LDAP authentication is failing, follow these steps:

  1. Edit log4j.properties (instructions), locate the lines:

    log4j.category.com.opensymphony = WARN, console
    log4j.additivity.com.opensymphony = false

    Duplicate these, and change the first copy to:

    log4j.category.com.opensymphony.user.provider.ldap = DEBUG, console
    log4j.additivity.com.opensymphony.user.provider.ldap = false

    Restart JIRA to apply your change. This change will turn up logging for the LDAP authentication module.

  2. When next trying to log in, you should see extra logs on stdout. A successful authentication looks like this:

    DEBUG [user.provider.ldap.LDAPCredentialsProvider] LDAPCredentialsProvider $Revision: 1.2 $ initializing
    DEBUG [user.provider.ldap.LDAPCredentialsProvider] 'jturner' will be handled by LDAP
    DEBUG [user.provider.ldap.LDAPCredentialsProvider] 'jturner' will be handled by LDAP
    DEBUG [user.provider.ldap.LDAPCredentialsProvider] 'jturner' will be handled by LDAP
    DEBUG [user.provider.ldap.LDAPCredentialsProvider] Doing initial search:
     username='cn=admin,dc=atlassian,dc=com', password='secret', base='ou=People,dc=atlassian,dc=com', filter='uid=jturner'
    DEBUG [user.provider.ldap.LDAPCredentialsProvider] Found users
    DEBUG [user.provider.ldap.LDAPCredentialsProvider] Searching below 'uid=jturner,ou=People,dc=atlassian,dc=com' for 'uid=jturner'
    DEBUG [user.provider.ldap.LDAPCredentialsProvider] User 'jturner' successfully authenticated; caching for 1800000 ms
                     

    This log was generated with the following to osuser.xml:

    <provider class="com.opensymphony.user.provider.ldap.LDAPCredentialsProvider">
    <property name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</property>
    <property name="java.naming.provider.url">ldap://localhost:389</property>
    <property name="searchBase">ou=People,dc=atlassian,dc=com</property>
    <property name="uidSearchName">uid</property>
    <property name="java.naming.security.principal">cn=admin,dc=atlassian,dc=com</property>
    <property name="java.naming.security.credentials">secret</property>
    <property name="exclusive-access">true</property>
    </provider>
                     
  3. If you have problems, try emulating the operations performed by the LDAP authentication provider. The LDAP authentication provider works by first doing an search for the specified username, searching from base searchBase, using query uidSearchName=username, authenticating using the principal and credentials properties if present, or doing an anonymous search otherwise. If an entry is found, it then tries to log in to LDAP using the specified matching username and specified password.

    Note
    If you get an error message javax.naming.PartialResultException: Unprocessed Continuation Reference(s), try adding <property name="java.naming.referral">follow</property> to the LDAPCredentialsProvider section.