掲示板

Liferay 6.1 - LDAP Configuration - Final

thumbnail
9年前 に Raul Barros によって更新されました。

Liferay 6.1 - LDAP Configuration - Final

New Member 投稿: 2 参加年月日: 14/01/30 最新の投稿
Hello folks,

So, I have recently configured a Liferay Portal 6.1 for one company, and despite doing a research on this specific case, I couldn't find any solution to my problem.

To avoid you from doing all this research, I'm going to post here all the steps that it takes to successfully setup the LDAP integration on Liferay 6.1 GA3.

Note: We use the LDAPs here, and that's was my nemesis on the project, so I'm going to describe step by step each one settings: LDAP and LDAPS.

*In this settings, we are going to make an integration where the user authentication will be totally made on the LDAP.

Liferay 6.1 LDAP (Open LDAP) Settings:

1) Configuring the portal-ext.properties:

1.1) Omni Admin
If you are going to setup a LDAP authentication, its highly recommended that you point an Omni admin to the portal in the properties file.
By doing so, even if your settings don't match the LDAP configuration, you will be allowed to login in the Portal with this user to change settings.

To do so, you have to add the following annotation in your portal-ext.properties:

omniadmin.users=[USERID]

Eg:
#
# omni admin
#
omniadmin.users=10400


Now, lets get to the Portal settings:
As the admin, go to Control Panel > Configurations

In Configurations access the sub-menu Authentication.

After that, access the tab LDAP
Here you have two Checkboxes:

Enabled: Check this box to enable LDAP Authentication.
Required: Check this box if LDAP authentication is required. Liferay will then not allow a user to log in unless he or she can successfully bind to the LDAP directory first. Uncheck this box if you want to allow users with Liferay accounts but no LDAP accounts to log in to the portal.

Now click on the Add Buttom to setup the Ldap connection:

Server Name: The name of this connection, it doesnt interfere on the connection itself.

Default Values: If you check one of these radio buttons, the default settings for the selected LDAP connection will be displayed in each field. (It doesnt affect the connection at all, its basically a help emoticon)

Connection: Here a point of attention, if you are using LDAP you are going to enter something like that in this field:

ldap://[IP OF YOUR LDAP SERVER]:[LDAP PORT]

The LDAP default port is 389, so this field will look like:

ldap://10.100.155.255:389

Note: If you are using a security LDAP server, you have to change this field to:

ldaps://[IP OF YOUR LDAP SERVER]:[LDAPS PORT]

The LDAPS default port is 636, so this field will look like:

ldaps://10.100.155.255:636

Base DN:This is the tree where Liferay is going to look for users to import, its not a required field, but I'm going to show an example of how you can fill this field:

LDAP TREE EXAMPLE:

dc=myorganization
ou=myldaptree1
ou=myldaptree2
ou=myldaptree3
ou=users
cn=user.ldap1
cn=user.ldap2
cn=user.ldap3
cn=user.ldap4


In this example, I want to Import the users in the myldaptree3, to do so Im going to configure the Base DN the following way:
ou=myldaptree3,dc=myorganization

Principal: This is the user that Liferay are going to use to login in the LDAP server.

Eg:
cn=admin,dc=myorganization

Credentials: This is your organization credentials, there's no secret to fill this field.

Now you can click on the Test Connection buttom, if everything is fine, than you are going to see a popup telling that Liferay were configured with success.

Note: If after those steps you still can't connect in the LDAP server heres goes a tip:
If you are using LDAPS, you need to run the keytool utility in this server, in order to generate an valid certificate that gonna be checked by your LDAP server.

The keytool have to be executed in the order to add this certificate in the JDK that you are using to run Liferay.

The certificate is issued by the LDAP server.

Eg:
keytool -import -trustcacerts -keystore /some/path/jdk1.5.0_11/jre/lib/security/cacerts -storepass changeit -noprompt -alias MyRootCA -file /some/path/MyRootCA.cer


Assuming that you connect successfully to the LDAP, now its time to set a filter to import users.

Authentication Filter: The LDAP attribute that is going to be used as primary key to authentication.

If you use username as primary key, than your settings are going to look something like this:
(cn=@screen_name@)

In other hand, if you user email, your settings gonna look like this:
(mail=@email_address@)

Lets dismember those lines:

(cn=@screen_name@)

CN is your username attribute in the LDAP tree.

(cn=@screen_name@)

SCREEN_NAME in this example is the CN equivalent in your Liferay portal.

Import Filter: Here you are going to set a filter of importing based on the LDAP attributes.

Eg:
Let's assume you have an user tree in LDAP that looks like this:

objectClass: inetOrgPerson (structural)
objectClass: organizationalPerson (structural)
objectClass: person (structural)
objectClass: top (abstract)
cn: user.liferay
givenName: User
sn: Surname
mail: user.mail@liferay.com
description: LiferayUser
ou: LiferayGroup
title: developer
userPassword: password123


objectClass: inetOrgPerson (structural)
objectClass: organizationalPerson (structural)
objectClass: person (structural)
objectClass: top (abstract)
cn: user2.liferay
givenName: User2
sn: Surname
mail: user2.mail@liferay.com
description: LiferayUser
ou: LiferayGroup
title: developer
userPassword: password123

Than you need to import users who have the attribute description as LiferayUser.

For that you can use the following filter:
(&(objectClass=person)(description=LiferayUser))

This way, the Liferay Portal is only going to import users that has the attribute description = LiferayUser

If you want to import all users, you can simply use this:
(objectClass=person)

You also can refine more your filter, lets import only the users with the LiferayUser description and the LiferayGroup ou.
(&(objectClass=person)(ou=LiferayGroup)(description=LiferayUser))

Now lets get to the user mapping.

This step is very important, here you are going to tell Liferay wich Liferay attribute each LDAP attribute mean.
Lets map the LDAP tree that I gave as example

Screen Name: cn
Password: userPassword
Email Address: mail
First Name: givenName
Last Name: sn
Job Title: title

Now you can click on the Test LDAP Users buttom and check if everything is fine.

Note: This step was a pain for me, cause the first time I setup the LDAP in my Portal, the LDAP wasnt have all the required attributes.

If you dont have e-mail address configured in your LDAP, you can add those variables in portal-ext.properties in order to generate a random e-mail for the users who dont have e-mail:

#
# Doesnt require email address
#
users.email.address.required=false

#
# mail generator (this is a default class of liferay that generate random email addresses)
#
users.email.address.generator=com.liferay.portal.security.auth.DefaultEmailAddressGenerator

#
# Email auto suffix (this is the default suffix of the generated emails)
#
users.email.address.auto.suffix=@no-emailaddress.com


By doing those configurations, you shall be allowed to see all users in your LDAP server.

Now we have to setup the way that LDAP is going to validate users that attempt to login in the portal.

1.2) Password method
Now you have to open your portal-ext.properties, and do the following changes:
If you are going to leave all the authentication in LDAP hands, you need to set the method of authentication.
In this example, Im going to set the authentication method "Password compare", by adding the anotation in portal-ext.properties:

#
# ldap auth method
#
ldap.auth.method=password-compare


This method simply gets the password inputed by the user in the login action, and compare with the one registered in LDAP.

*Note: Here's an issue that I found in this step: Even using this method and typing the same password registered in LDAP, my user wont log in.
After adding some prints in the method I realised where the problem was:
In LDAP I had the password encrypted as MD5, and because of that I have to set the following anotation:

#
# ldap encryption
#
ldap.auth.password.encryption.algorithm=MD5


But, even with the anotation I couldn't log in the portal, so I printed both passwords to see what was the system comparing.

In few words, the portal was adding the tag {MD5} in front of the password every time he tried to compare. And my LDAP wasnt configured to send an MD5 password, he just had the MD5 there not knowing that thats password was encrypted.

The portal was doing the following comparation:
{MD5}5f4dcc3b5aa765d61d8327deb882cf99 = 5f4dcc3b5aa765d61d8327deb882cf99 ?

And of course the result was NO.

Here we get to the step that I'm not proud of: Edit the LDAPAuth.class in the portal-impl.jar

You have to open this class in eclipse, edit the method authenticate to compare without the {MD5} tag, and put it back to the portal-impl.jar

Here how my authenticate method looks like now:

protected LDAPAuthResult authenticate(LdapContext ctx, long companyId, Attributes attributes, String userDN, String password)
    throws Exception
  {
    LDAPAuthResult ldapAuthResult = new LDAPAuthResult();

    String authMethod = PrefsPropsUtil.getString(
      companyId, "ldap.auth.method");
    InitialLdapContext innerCtx = null;

    if (authMethod.equals("bind")) {
      try {
        Hashtable env = 
          ctx.getEnvironment();

        env.put("java.naming.security.principal", userDN);
        env.put("java.naming.security.credentials", password);
        env.put(
          "java.naming.referral", 
          PrefsPropsUtil.getString(
          companyId, "ldap.referral"));

        env.put("com.sun.jndi.ldap.connect.pool", "false");

        innerCtx = new InitialLdapContext(env, null);

        Control[] responseControls = innerCtx.getResponseControls();

        ldapAuthResult.setAuthenticated(true);
        ldapAuthResult.setResponseControl(responseControls);
      }
      catch (Exception e) {
        if (_log.isDebugEnabled()) {
          _log.debug(
            "Failed to bind to the LDAP server with userDN " + 
            userDN + " and password " + password);
        }

        _log.error("Failed to bind to the LDAP server", e);

        ldapAuthResult.setAuthenticated(false);
        ldapAuthResult.setErrorMessage(e.getMessage());
      }
      finally {
        if (innerCtx != null) {
          innerCtx.close();
        }
      }
    }
    else if (authMethod.equals("password-compare")) {
      Attribute userPassword = attributes.get("userPassword");

      if (userPassword != null) {
        String ldapPassword = new String((byte[])userPassword.get());

        String encryptedPassword = password;

        String algorithm = PrefsPropsUtil.getString(
          companyId, 
          "ldap.auth.password.encryption.algorithm");

        if (Validator.isNotNull(algorithm))
        {
          if (_log.isWarnEnabled()) {
            _log.warn(
              "Algoritimo de encriptacao selecionado " + algorithm);
          }

          MessageDigest md = null;

          md = MessageDigest.getInstance(algorithm);

          BigInteger hash = new BigInteger(1, md.digest(encryptedPassword.getBytes()));

          encryptedPassword = hash.toString(16);
        }

        if (ldapPassword.equals(encryptedPassword)) {
          ldapAuthResult.setAuthenticated(true);
        }
        else {
          ldapAuthResult.setAuthenticated(false);

          if (_log.isWarnEnabled()) {
            _log.warn(
              "Passwords do not match for userDN " + userDN + encryptedPassword);
          }
        }
      }
    }

    return ldapAuthResult;
  }


Now you can successfully log in your portal with the LDAP user HURRAY emoticon
thumbnail
7年前 に Andrew Jardine によって更新されました。

RE: Liferay 6.1 - LDAP Configuration - Final

Liferay Legend 投稿: 2416 参加年月日: 10/12/22 最新の投稿
Hey Raul -- thanks for sharing. There is also documentation on Liferay's site for how to configure DLAP -- https://dev.liferay.com/discover/portal/-/knowledge_base/6-1/integrating-liferay-users-into-your-enterprise

There is no reference to the omni admin because it basically creates a back door -- I certainly would not advise going into production with that. A better approach is to Enable LDAP but not require it initially so that you can use the test@liferay.com account (which is not in the directory store but is in Liferay) to still gain access to the portal. Once you have your (future) admin user imported into Liferay (from LDAP) you can set the role and then toggle the LDAP Required. Just be careful when using the omni admin.

I would also recommend that you try to convince your project team / employer / client whatever to use a more recent version of Liferay. 6.1 is not just an old version, it's an ANCIENT version now, years out of date. The move to 7.0 might be too jarring for your project at this stage, but I would consider at least moving to 6.2 as there are a number of improvements you could benefit from including one that I found to be a tremendous improvement on performance -- parallel portlet rendering. This is just one of many many features that shipped with 6.2 that are awesome, and 6.2 is not so drastically different that 6.1 (architecturally) so it'll be an easier move than 7.0. 6.2 is probably going to going to be sunset pretty soon though so even if you do move to it, you should probably also evaluate what it will take to go to 7 -- always assuming that Liferay is part of your future direction of course emoticon
thumbnail
7年前 に Raul Barros によって更新されました。

RE: Liferay 6.1 - LDAP Configuration - Final

New Member 投稿: 2 参加年月日: 14/01/30 最新の投稿
Hey Andrew,

Thanks for taking the time to answer this post.

I've created this post back in the beginning of 2014, Liferay 6.2 was pretty recent, and there was way too little information to be found about it back then, there wasn't so many apps available in the marketplace for 6.2 either, that's why I decided to go the safe way with 6.1

I can't remember all the information that I've researched back then, but my main problem was the way Liferay was using to compare the encrypted password with LDAP (putting the {MD5} in front of the password) and there was no information about that that I could find in the knowledge base, that's why I decided to create this post, to help others with the same problem.

Cheers,
Raul Barros