LDAP Integration
| 
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:
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:
| Property | Required | Description | Example |
| 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.url | Yes | LDAP URL of your server |
ldap://localhost:389 |
| searchBase | Yes | The 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'.
|
| uidSearchName | Yes | Attribute expected to contain username |
Typically uid, or sAMAccountName for MS ActiveDirectory. |
| java.naming.security.principal | No | Username 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.credentials | No | Password for initial login. Not required if anonymous
lookups are allowed. |
|
| providerName | No | unique name for this LDAP provider. Useful when
you specify multiple LDAP providers (allowing fallback), and need to distinguish them in the debug logs. |
|
| cacheTimeout | No | The 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:
- Log in as a user with the 'JIRA System Administrators' global permission.
-
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.
-
Under the 'System' sub-menu in the left-hand navigation column, click the 'Logging &
Profiling' link.
-
The 'Logging & Profiling' page will display.
Click the 'Edit' link next to 'com.atlassian.jira.web.action.util.LDAPConfigurer'
-
Change the logging level to 'DEBUG', then click 'Update'. This temporarily turns up logging for the JIRA LDAP Configurer.
-
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:
-
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.
-
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>
-
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.