Introduction #

This guide explains how to create a CAS (Custom Authentication System) using your own authentication modules in Liferay. Included are a few samples.

There are two authentication classes: com.liferay.portal.security.auth.Authenticator and com.liferay.portal.security.auth.AutoLogin. Which class or classes to use depends on your environment and requirements. Hopefully this guide will help you design your custom Liferay authentication.

__TOC__

Requirements #

This only requirement is that the Liferay development environment is setup. This is not an absolute requirement but is the recommended practice (see the topic Setting up the Extension Environment)

Login portlet #

I wanted to write a few notes about this portlet since login/authentication starts here. This is a struts portlet and is defined in struts-config.xml. It has a view and an action. The view displays a login form when not authenticated or a welcome message when logged in. The login action calls com.liferay.portal.action.LoginAction when the user clicks on the submit form button. It is recommended to at least take a look at the LoginAction code to see what the business logic does and how it initiates the authentication process - it makes a call to com.liferay.portal.service.UserLocalServiceUtil (which will call UserLocalServiceImpl).

Authenticaton Pipeline #

The behavior of the Authenticator class is governed by the Authentication Pipeline. I am going to print out an excerpt of the Authentication Pipeline taken from portal.properties and will describe some of the properties afterwards.

    #
    # Input a list of comma delimited class names that implement
    # com.liferay.portal.security.auth.Authenticator. These classes will run
    # before or after the portal authentication begins.
    #
    # The Authenticator class defines the constant values that should be used
    # as return codes from the classes implementing the interface. If
    # authentication is successful, return SUCCESS; if the user exists but the
    # passwords do not match, return FAILURE; and if the user does not exist on
    # the system, return DNE.
    #
    # Constants in Authenticator:
    #     public static final int SUCCESS = 1;
    #     public static final int FAILURE = -1;
    #     public static final int DNE = 0;
    #
    # In case you have several classes in the authentication pipeline, all of
    # them have to return SUCCESS if you want the user to be able to login. If
    # one of the authenticators returns FAILURE or DNE, the login fails.
    #
    # Under certain circumstances, you might want to keep the information in the
    # portal database in sync with an external database or an LDAP server. This
    # can easily be achieved by implementing a class via LDAPAuth that updates
    # the information stored in the portal user database whenever a user signs
    # in.
    #
    # Each portal instance can be configured at run time to either authenticate
    # based on user ids or email addresses. See the Admin portlet for more
    # information.
    #
    # Available authenticators are:
    #     com.liferay.portal.security.auth.LDAPAuth
    #
    # See the LDAP properties to configure the behavior of the LDAPAuth class.
    #
    auth.pipeline.pre=com.liferay.portal.security.auth.LDAPAuth
    #auth.pipeline.post=

    #
    # Set this to true to enable password checking by the internal portal
    # authentication. If set to false, you're essentially delegating password
    # checking is delegated to the authenticators configured in
    # "auth.pipeline.pre" and "auth.pipeline.post" settings.
    #
    auth.pipeline.enable.liferay.check=true

The business logic for the Authentication Pipeline is contained in com.liferay.portal.service.impl.UserLocalServiceImpl. There is a auth.pipeline.pre and a auth.pipeline.post property where you define the Authenticator classes you wish to use. I will explain auth.pipeline.enable.liferay.check property's affect also. This is essentially the order of the pipeline logic (each step must be successful to continue to the next step):

  1. First the Authenticators in the pre-pipeline are called in the order that they are listed. For authentication to be successful each Authenticator module has to return SUCCESS. An empty pre-pipeline is returns success.
  2. The user's account is checked to see if it is locked out and the user's password is checked to see if it has expired. Both conditions have to be false to continue.
  3. If auth.pipeline.enable.liferay.check is 'true' then Liferay will take the username/email address/userid (depending on authentication configuration) & password and validate those credentials in the Liferay database. This requires that the Liferay account for the user has been created AND a password has been stored for the user. If auth.pipeline.enable.liferay.check is 'false' this step is skipped.
  4. Finally the Authenticators in the post-pipeline are called in the order that they are listed. Similar to the pre-pipeline for the post-pipeline authentication to be successful each Authenticator module has to return SUCCESS.

Modifiying the Authentication Pipeline #

Because i (Hermann|Hermann 02:21, 15 August 2007 (PDT)) didn't really like this setting:

    # In case you have several classes in the authentication pipeline, all of
    # them have to return SUCCESS if you want the user to be able to login. If
    # one of the authenticators returns FAILURE or DNE, the login fails.

i modified several Things in the AuthPipeline and made this configurable thour portal.properties.

First i created a PropsUtil which extends Liferays com.liferay.portal.util.PropsUtil:

public class PropsUtil extends com.liferay.portal.util.PropsUtil {
	public static final String LIFERAY_AUTH_REQUIRED = "liferay.auth.required";
	public static final String AUTH_STAGED = "auth.pipeline.stagedAuth";
...
}
//end

This allows me to use my PropsUtil class wherever i need it and i can add as many Configuration Values as i want.

Then i modified the AuthPipeline to use my AUTH_STAGED Property:

public class AuthPipeline {

	public static int authenticateByEmailAddress(
			String[] classes, long companyId, String emailAddress,
			String password, Map headerMap, Map parameterMap)
		throws AuthException {

		return _authenticate(
			classes, companyId, emailAddress, password,
			CompanyImpl.AUTH_TYPE_EA, headerMap, parameterMap);
	}

	public static int authenticateByScreenName(
			String[] classes, long companyId, String screenName,
			String password, Map headerMap, Map parameterMap)
		throws AuthException {

		return _authenticate(
			classes, companyId, screenName, password, CompanyImpl.AUTH_TYPE_SN,
			headerMap, parameterMap);
	}

	public static int authenticateByUserId(
			String[] classes, long companyId, long userId, String password,
			Map headerMap, Map parameterMap)
		throws AuthException {

		return _authenticate(
			classes, companyId, String.valueOf(userId), password,
			CompanyImpl.AUTH_TYPE_ID, headerMap, parameterMap);
	}

	public static void onFailureByEmailAddress(
			String[] classes, long companyId, String emailAddress,
			Map headerMap, Map parameterMap)
		throws AuthException {

		_onFailure(
			classes, companyId, emailAddress, CompanyImpl.AUTH_TYPE_EA,
			headerMap, parameterMap);
	}

	public static void onFailureByScreenName(
			String[] classes, long companyId, String screenName,
			Map headerMap, Map parameterMap)
		throws AuthException {

		_onFailure(
			classes, companyId, screenName, CompanyImpl.AUTH_TYPE_SN, headerMap,
			parameterMap);
	}

	public static void onFailureByUserId(
			String[] classes, long companyId, long userId, Map headerMap,
			Map parameterMap)
		throws AuthException {

		_onFailure(
			classes, companyId, String.valueOf(userId),
			CompanyImpl.AUTH_TYPE_ID, headerMap, parameterMap);
	}

	public static void onMaxFailuresByEmailAddress(
			String[] classes, long companyId, String emailAddress,
			Map headerMap, Map parameterMap)
		throws AuthException {

		onFailureByEmailAddress(
			classes, companyId, emailAddress, headerMap, parameterMap);
	}

	public static void onMaxFailuresByScreenName(
			String[] classes, long companyId, String screenName,
			Map headerMap, Map parameterMap)
		throws AuthException {

		onFailureByScreenName(
			classes, companyId, screenName, headerMap, parameterMap);
	}

	public static void onMaxFailuresByUserId(
			String[] classes, long companyId, long userId, Map headerMap,
			Map parameterMap)
		throws AuthException {

		onFailureByUserId(classes, companyId, userId, headerMap, parameterMap);
	}

	private static int _authenticate(
			String[] classes, long companyId, String login, String password,
			String authType, Map headerMap, Map parameterMap)
		throws AuthException {

		// Set the default Liferay Behaviour
		boolean stagedAuth = false;
		try {
			stagedAuth = PrefsPropsUtil.getBoolean(PropsUtil.AUTH_STAGED);
		} catch (PortalException pe) {
			_log.error("PortalException: Error reading Value auth.pipeline.stagedAuth from Config File");
			if (_log.isDebugEnabled()) {
				_log.debug("PortalException reading Property auth.pipeline.stagedAuth",pe);
			}
		} catch (SystemException se) {
			_log.error("SystemException: Error reading Value auth.pipeline.stagedAuth from Config File");
			if (_log.isDebugEnabled()) {
				_log.debug("SystemException reading Property auth.pipeline.stagedAuth",se);
			}
		}

		if (_log.isDebugEnabled())
			_log.debug("Auth Pipeline: stagedAuth is: " + stagedAuth);
		
		if ((classes == null) || (classes.length == 0)) {
			return 1;
		}

		for (int i = 0; i < classes.length; i++) {
			String className = classes[i];

			_log.debug("Trying Auth Class " + i + " with Name: " + className);
			
			if (Validator.isNotNull(className)) {
				Authenticator auth =
					(Authenticator)InstancePool.get(classes[i]);

				try {
					int authResult = Authenticator.FAILURE;

					if (authType.equals(CompanyImpl.AUTH_TYPE_EA)) {
						authResult = auth.authenticateByEmailAddress(
							companyId, login, password, headerMap,
							parameterMap);
					}
					else if (authType.equals(CompanyImpl.AUTH_TYPE_SN)) {
						authResult = auth.authenticateByScreenName(
							companyId, login, password, headerMap,
							parameterMap);
					}
					else if (authType.equals(CompanyImpl.AUTH_TYPE_ID)) {
						long userId = GetterUtil.getLong(login);

						authResult = auth.authenticateByUserId(
							companyId, userId, password, headerMap,
							parameterMap);
					}
					if (stagedAuth) {
						if (authResult == Authenticator.SUCCESS) {
							return authResult;
						}
					} else {
						if (authResult != Authenticator.SUCCESS) {
							return authResult;
						}
					}
				}
				catch (AuthException ae) {
					throw ae;
				}
				catch (Exception e) {
					throw new AuthException(e);
				}
			}
		}
		if (stagedAuth) {
			return Authenticator.FAILURE;
		} else {
			return Authenticator.SUCCESS;
		}
	}

	private static void _onFailure(
			String[] classes, long companyId, String login, String authType,
			Map headerMap, Map parameterMap)
		throws AuthException {

		if ((classes == null) || (classes.length == 0)) {
			return;
		}

		for (int i = 0; i < classes.length; i++) {
			String className = classes[i];

			if (Validator.isNotNull(className)) {
				AuthFailure authFailure =
					(AuthFailure)InstancePool.get(classes[i]);

				try {
					if (authType.equals(CompanyImpl.AUTH_TYPE_EA)) {
						authFailure.onFailureByEmailAddress(
							companyId, login, headerMap, parameterMap);
					}
					else if (authType.equals(CompanyImpl.AUTH_TYPE_SN)) {
						authFailure.onFailureByScreenName(
							companyId, login, headerMap, parameterMap);
					}
					else if (authType.equals(CompanyImpl.AUTH_TYPE_ID)) {
						long userId = GetterUtil.getLong(login);

						authFailure.onFailureByUserId(
							companyId, userId, headerMap, parameterMap);
					}
				}
				catch (AuthException ae) {
					throw ae;
				}
				catch (Exception e) {
					throw new AuthException(e);
				}
			}
		}
	}

	private static Log _log = LogFactoryUtil.getLog(AuthPipeline.class);
	
}
// end

This way, i can set the auth.pipeline.stagedAuth = true in the portal.properties and get a Pipeline behaviour where only one Authenticator has to return success on login. This makes sense when you have several Auth systems, where only a part of your users are registered. See Forums: Authentication suggestions to Liferay devs and Forums: Authentication Pipeline Also i didn't like that one has to import the User Passwords into Liferay (one more possible security hole).

Hermann|Hermann 02:21, 15 August 2007 (PDT)

Authenticator #

As mentioned earlier the Authenticator's behavior is controlled by the pipeline above. So to use an Authenticator class just implement the class and supply it with your institution's authentication logic. There are three Authenticator methods; which method is called depends on how Liferay's authentication type is setup (AuthType). Currently Liferay supports three AuthTypes: email, username/screenname, and userid. AuthType is managed in the Enterprise Admin portlet -> Settings tab -> Authentication tab -> 'How do users authenticate?' Attempting to authenticate with other attributes for login will require customization outside of topics discussed here. Look to the sample Authenticators provided in this guide for help.

AutoLogin #

This class is a filter that is called when either a user has not be authenticated or there previous session has timed out. The AutoLogin classes are defined in auto.login.hooks property. The classes are called in the order that they are defined. AutoLogin class attempts to "automatically" log in users. It appears to be automatic because the user does not necessarily have to interact (e.g. enter login information). For example if the user has already authenticated to a Single-Sign-On (SSO) server at the institution, the AutoLogin module may be able to access data from the SSO to log the user automatically into Liferay. Another example is the RememberMeAutoLogin module that uses a cookie that will automatically log in a user who has previously logged in.

Sample Authenticator - LiferayAuth #

This Authenticator takes the user's credentials and authenticates the user against the Liferay database. This is essentially doing what occurs when auth.pipeline.enable.liferay.check is 'true'. IMO, this should be packaged with Liferay.

public class LiferayAuth implements Authenticator {

        public int authenticateByEmailAddress( long companyId, String emailAddress, String password, Map headerMap, Map parameterMap)
                throws AuthException {

                try {
                        return authenticate( companyId, emailAddress, StringPool.BLANK, 0, password);
                }
                catch (Exception e) {
                        _log.error(e, e);
                        throw new AuthException(e);
                }
        }

        public int authenticateByScreenName( long companyId, String screenName, String password, Map headerMap, Map parameterMap)
                throws AuthException {

                try {
                        return authenticate( companyId, StringPool.BLANK, screenName, 0, password);
                }
                catch (Exception e) {
                        _log.error(e, e);
                        throw new AuthException(e);
                }
        }

        public int authenticateByUserId( long companyId, long userId, String password, Map headerMap, Map parameterMap)
                throws AuthException {

                try {
                        return authenticate( companyId, StringPool.BLANK, StringPool.BLANK, userId, password);
                }
                catch (Exception e) {
                        _log.error(e, e);

                        throw new AuthException(e);
                }
        }

        protected int authenticate( long companyId, String emailAddress, String screenName, long userId, String password) throws Exception {
                if (_log.isDebugEnabled()) {
                        _log.debug("Authenticator is enabled");
                }

                User user = null;
                try {
                        if (!emailAddress.equals(StringPool.BLANK)) {
                                user = UserUtil.findByC_EA(companyId, emailAddress);
                        } else if (!screenName.equals(StringPool.BLANK)) {
                                user = UserUtil.findByC_SN(companyId, screenName);
                        } else if (userId > 0) {
                                user = UserUtil.findByC_U(companyId, userId);
                        } else {
                                return Authenticator.DNE;
                        }
                }
                catch (NoSuchUserException nsue) {
                        return Authenticator.DNE;
                }
                String encPwd = PwdEncryptor.encrypt(password, user.getPassword());
                if (!user.getPassword().equals(encPwd)) {
                        _log.debug("Passwords did not match: "+user.getPassword()+" || "+encPwd);
                        return FAILURE;
                }
                return SUCCESS;
        }

        private static Log _log = LogFactoryUtil.getLog(LiferayAuth.class);
}
// end

Sample Authenticator - LiferayAuth (Matching the modified AuthPipeline) #

Here is my Version of the LiferayAuth class, I've added some additional Configuration liferay.auth.required = true/false and reflected this by a Method protected int authenticateRequired(). This allows me to set liferay.auth.required = true; auth.pipeline.stagedAuth = true; and auth.pipeline.enable.liferay.check=false, this way i don't need to import any passwords to the Liferay DB (for example with Ldap Auth, or some other system).

Note that Liferay has the wonderful tendancy to reduce everything to lower case - especially usernames / mail addresses which may cause grief when trying to talk to other systems - LDAP in particular. You can get the original strings that the user typed by pulling them off the parameterMap. This hash map has a bunch of keys that are tied to String[] objects, of which most of the time only the first value is filled in. If you ask for the 'login' entry, you will find that index [0] contains the username value (mail or screen name depending on how you configured Liferay) that the user typed.

public class LiferayAuth implements Authenticator {

	public int authenticateByEmailAddress(
			long companyId, String emailAddress, String password, Map headerMap,
			Map parameterMap)
		throws AuthException {

		try {
			return authenticate(
				companyId, emailAddress, StringPool.BLANK, 0, password, headerMap, parameterMap);
		}
		catch (Exception e) {
			_log.error(e, e);

			throw new AuthException(e);
		}
	}

	public int authenticateByScreenName(
			long companyId, String screenName, String password, Map headerMap,
			Map parameterMap)
		throws AuthException {

		try {
			return authenticate(
				companyId, StringPool.BLANK, screenName, 0, password, headerMap, parameterMap);
		}
		catch (Exception e) {
			_log.error(e, e);

			throw new AuthException(e);
		}
	}

	public int authenticateByUserId(
			long companyId, long userId, String password, Map headerMap,
			Map parameterMap)
		throws AuthException {

		try {
			return authenticate(
				companyId, StringPool.BLANK, StringPool.BLANK, userId,
				password, headerMap, parameterMap);
		}
		catch (Exception e) {
			_log.error(e, e);

			throw new AuthException(e);
		}
	}

	protected int authenticate(
			long companyId, String emailAddress, String screenName, long userId,
			String password, Map headerMap, Map parameterMap)
		throws Exception {

		if (_log.isDebugEnabled())
			_log.debug("Auth via Liferay...");
		
		// No ScreenName/email/userid => no login
		if (screenName == StringPool.BLANK && PrefsPropsUtil.getString(PropsUtil.COMPANY_SECURITY_AUTH_TYPE).equals(CompanyImpl.AUTH_TYPE_SN)) {
			_log.error("No screenName given, but screenName required to Auth.");
			return authenticateRequired(companyId, userId, emailAddress, FAILURE);
		} else if (emailAddress == StringPool.BLANK && PrefsPropsUtil.getString(PropsUtil.COMPANY_SECURITY_AUTH_TYPE).equals(CompanyImpl.AUTH_TYPE_EA)) {
			_log.error("No emailAdress given, but email required to Auth.");
			return authenticateRequired(companyId, userId, emailAddress, FAILURE);
		} else if (userId <= 0 && PrefsPropsUtil.getString(PropsUtil.COMPANY_SECURITY_AUTH_TYPE).equals(CompanyImpl.AUTH_TYPE_ID)) {
			_log.error("No uid given, but uid required to Auth.");
			return authenticateRequired(companyId, userId, emailAddress, FAILURE);
		}

		int authResult = FAILURE;
		
		// check Authentication
		User user = null;

		try {
			if (screenName.equals(StringPool.BLANK) && emailAddress.equals(StringPool.BLANK)) {
				user = UserUtil.findByC_U(companyId, userId);							
			} else if (screenName.equals(StringPool.BLANK)) {
				user = UserUtil.findByC_EA(companyId, screenName);							
			} else if (emailAddress.equals(StringPool.BLANK)) {
				user = UserUtil.findByC_SN(companyId, screenName);
			}
		} catch (NoSuchUserException nsue) {
			_log.warn("No such User found: SN: " + screenName + "EA: " + emailAddress + " UID:" + userId);
			return authenticateRequired(
					companyId, userId, emailAddress, DNE);
		}
		
		// encrypt plain Password (encrypted passwd is needed for the salt)
		String encPwd = PwdEncryptor.encrypt(password, user.getPassword());
		
		// Check passwords are the same
		if (user.getPassword().equals(encPwd)) {
			authResult = SUCCESS;
			_log.debug("Auth succeeded: SN: " + screenName + "EA: " + emailAddress + " UID:" + userId);
			return authResult;
		}		

		if (authResult != SUCCESS) {
			if (_log.isInfoEnabled())
				_log.info("Liferay Auth failed: SN: " + screenName + "EA: " + emailAddress + " UID:" + userId);
			return authenticateRequired(
				companyId, userId, emailAddress, FAILURE);
		}
		
		//should never get here...
		_log.error("This Message should never appear! BUG!");
		return SUCCESS;
	}


	protected int authenticateRequired(
			long companyId, long userId, String emailAddress, int failureCode)
		throws Exception {

		if (PrefsPropsUtil.getBoolean(
				companyId, PropsUtil.LIFERAY_AUTH_REQUIRED)) {

			return failureCode;
		}
		else {
			_log.debug("Overridden Result (req=false), returning SUCCESS");
			return SUCCESS;
		}
	}

	private static Log _log = LogFactoryUtil.getLog(LiferayAuth.class);

}
// end

Hermann|Hermann 02:30, 15 August 2007 (PDT)

Sample Authenticator - SuccessAuth #

This Authenticator always returns success. Mainly only good for testing.

public class SuccessAuth implements Authenticator {

        public int authenticateByEmailAddress( long companyId, String emailAddress, String password, Map headerMap, Map parameterMap) {
                return authenticate();
        }

        public int authenticateByScreenName( long companyId, String screenName, String password, Map headerMap, Map parameterMap) {
                return authenticate();
        }

        public int authenticateByUserId( long companyId, long userId, String password, Map headerMap, Map parameterMap) {
                return authenticate();
        }

        protected int authenticate( ) {
                _log.debug("returning SUCCESS");
                return SUCCESS;
        }

        private static Log _log = LogFactoryUtil.getLog(SuccessAuth.class);
}
// end

Sample Authenticator - FailureAuth #

This Authenticator always returns failure. Mainly good for testing.

public class FailureAuth implements Authenticator {

        public int authenticateByEmailAddress( long companyId, String emailAddress, String password, Map headerMap, Map parameterMap) {
                return authenticate();
        }

        public int authenticateByScreenName( long companyId, String screenName, String password, Map headerMap, Map parameterMap) {
                return authenticate();
        }

        public int authenticateByUserId( long companyId, long userId, String password, Map headerMap, Map parameterMap) {
                return authenticate();
        }

        protected int authenticate( ) {
                _log.debug("returning FAILURE");
                return FAILURE;
        }

        private static Log _log = LogFactoryUtil.getLog(FailureAuth.class);
}
// end

Sample AutoLogin - ShibbolethAutoLogin #

At our institution we use Shibboleth for web SSO. This requires that we place an Apache HTTP server in front of our Liferay portal. Shibboleth passes user data via HTTP headers - since the Authenticator class does not have access to the HttpServletRequest we had to use an AutoLogin class. Our Shibboleth AutoLogin module looks for these http headers for user information (uid, email, name, etc) but we can also pass other data such as authorization, group, etc. The application, Liferay in this case, will never have access to the user's password. So in our case we have to make up a password to store in the Liferay database.

A couple of other things to note in this module:

  • I allow Omniadmins to impersonate users in this module. This is slightly different from the impersonate feature within Liferay. In this module if the user doesnt have a Liferay account one will be created.
  • This module will auto-create a Liferay account for the user if they don't have one already.
  • There are a number of features I want to add: pull group information from Shibboleth/LDAP, synchronize user group memberships, authorization check (is the user authorized to use Liferay), modify the auto-create (mainly for a more secure auto-generated password), logout, allow accounts with duplicate email addresses (in our Enterprise users can have multiple accounts that use the same email address).

Note: This is not production code - it is being used for a proof of concept.

public class ShibbolethAutoLogin implements AutoLogin {

        public String[] login(HttpServletRequest req, HttpServletResponse res)
                throws AutoLoginException {

                String[] credentials = null;
                String userScreenName = null;
                String uscpvid = null;
                String mail = null;
                String displayName = null;
                long userId = 0;
                String passwd = null;
                String userName = req.getParameter("userName");
                long companyId = 0;

                try {
                        companyId = PortalUtil.getCompany(req).getCompanyId();

                        userScreenName = req.getHeader(PrefsPropsUtil.getString(companyId,USCPropsUtil.USC_AUTH_SHIB_UID));
                        uscpvid = req.getHeader(PrefsPropsUtil.getString(companyId,USCPropsUtil.USC_AUTH_SHIB_USCOWNERPVID));
                        mail = req.getHeader(PrefsPropsUtil.getString(companyId,USCPropsUtil.USC_AUTH_SHIB_MAIL));
                        displayName = req.getHeader(PrefsPropsUtil.getString(companyId,USCPropsUtil.USC_AUTH_SHIB_DISPLAYNAME));

                        userScreenName = uscpvid;
                        if (userScreenName == null || userScreenName.length() < 1) {
                                _log.error("Did not receive uid from Shibboleth");
                                return credentials;
                        }
                        if (Validator.isNotNull(userScreenName)) {
                                credentials = new String[3];

                                User user = UserLocalServiceUtil.getUserByScreenName(companyId, userScreenName);

                                if (OmniadminUtil.isOmniadmin(user.getUserId() )) {
                                         _log.error(user.getUserId()+" is an Omniadmin!");
                                        if (userName != null &&  userName.length() > 0) {
                                                _log.error("impersonating: "+userName);
                                                userId = UserLocalServiceUtil.getUserByScreenName(companyId,userName).getUserId();
                                                credentials[0] = String.valueOf(userId);
                                                userScreenName = userName;
                                        }
                                        else {
                                                credentials[0] = String.valueOf(user.getUserId());
                                        }
                                }
                                else {
                                         _log.error(user.getUserId()+" is not an Omniadmin!");
                                        credentials[0] = String.valueOf(user.getUserId());
                                }
                                credentials[1] = user.getPassword();
                                credentials[2] = Boolean.TRUE.toString();
                        }
                        return credentials;
                }
                catch (NoSuchUserException e) {
                }
                catch (Exception e) {
                        _log.error(StackTraceUtil.getStackTrace(e));
                        throw new AutoLoginException(e);
                }
                try {
                        long creatorUserId = 0;
                        boolean autoUserId = false;
                        boolean autoPassword = false;
                        // we have to set the password to something.  replace this in the
                        // future with something smarter
                        String password1 = "replaceme";
                        String password2 = "replaceme";
                        boolean autoScreenName = false;
                        String emailAddress = mail;
                        Locale locale = Locale.US;
                        String firstName = displayName;
                        String middleName = null;
                        String lastName = ".";
                        int prefixId = 0;
                        int suffixId = 0;
                        boolean male = true;
                        int birthdayMonth = Calendar.JANUARY;
                        int birthdayDay = 1;
                        int birthdayYear = 1970;
                        String jobTitle = null;
                        int organizationId = 0;
                        int locationId = 0;
                        boolean sendEmail = false;

                        // setting password to null returns errors (actually null)
                        User user = UserLocalServiceUtil.addUser(
                                creatorUserId, companyId, autoPassword, password1,
                                password2, autoScreenName, userScreenName, emailAddress, locale,
                                firstName, middleName, lastName, prefixId, suffixId,
                                male, birthdayMonth, birthdayDay, birthdayYear, jobTitle,
                                organizationId, locationId, sendEmail);


                        if (user == null) {
                                _log.error("LDAPImportUtil.addOrUpdateUser() returned null");
                        }
                        else {
                                // we want a null password but this is not working - why?
                                user.setPassword(null);
                        }
                        _log.error("finished calling: LDAPImportUtil.addOrUpdateUser()");
                        ldapLookup(companyId, userScreenName);

                        credentials = new String[3];
                        credentials[0] = String.valueOf(userId);
                        credentials[1] = password1;
                        credentials[2] = Boolean.FALSE.toString();

                        return credentials;
                }
                catch (Exception e) {
                        _log.error(StackTraceUtil.getStackTrace(e));
                        throw new AutoLoginException(e);
                }
        }
// end

Notes #

  • Users log in with either their screenname, email address, or (Liferay) userid. This can be changed to allow users to log in with other attributes but it would require modifications to various business layers. I believe all the classes are identified above.
0 Attachments
67529 Views
Average (1 Vote)
The average rating is 5.0 stars out of 5.
Comments
Threaded Replies Author Date
Is there a way to configure a custom... Rainer Montag January 8, 2009 7:46 AM
Is possible to disable authentication for a... Marco Bolzan September 24, 2009 3:57 AM
Hi, I am looking for a solution to invoke... Vishal G June 11, 2010 1:18 AM
Additional information for the above question I... Vishal G June 11, 2010 1:20 AM
Vishal, Did you get a reply on this? I have a... Dave Godbey July 2, 2010 11:34 AM
i'm attempting the same thing.. i have it... Gary Pinkham August 8, 2010 7:34 AM
Vishal or Dave, Did you find the solution?... Kalman Vincze January 4, 2011 11:28 PM
You can use PortalUtil class. to take the session Murat ÇOLAK January 19, 2011 1:07 AM
Hi, I'm using Liferay 6 and Eclipse. Which is... John F. Miller November 11, 2010 5:55 AM
Hi, I am looking for SSO solution with... manjula rathnayaka October 31, 2011 2:42 AM
@All I am trying to implement authentication of... Navnath Gajare November 2, 2011 12:36 AM
Hi, I developed a CAS. It's working in our... Mathieu Hicauber August 14, 2012 8:28 AM
I am using Liferay 6.1.1 the latest one and I... Durrab Khan August 26, 2012 1:21 AM
Can I insert a user with out a password?... Ishan A B Ambanwela March 9, 2014 12:19 AM

Is there a way to configure a custom Authenticator when using the OpenID Log In portlet ?

Im using Liferay 5.2.1. Custom Authenticator is called from Log In portlet, but not from OpenID Log In portlet.

Rainer
Posted on 1/8/09 7:46 AM.
Is possible to disable authentication for a portlet (ex. blog) ?
I use social office 1.5b
Posted on 9/24/09 3:57 AM.
Hi,

I am looking for a solution to invoke authentication webservice of my legacy application by creating a custom authentication mechanism in liferay. Can you please help me for this..I am not sure how to do this..

Regards
Vishal G
Posted on 6/11/10 1:18 AM in reply to Marco Bolzan.
Additional information for the above question
I am using Liferay 5.2.3.
Posted on 6/11/10 1:20 AM in reply to Vishal G.
Vishal,
Did you get a reply on this? I have a custom authenticator built for our legacy login web services, but I need to put a token returned by that web service on the request or session, or somehow that the portlets can access the token. I have yet to figure out how to do this.
Thanks,
Dave
Posted on 7/2/10 11:34 AM in reply to Vishal G.
i'm attempting the same thing.. i have it partially working.. I extended the RememberMeAutoLogin class to add the http session to a thread local variable. Then I created an Authenticator which I included in the auth pipeline pre hook.. in this class I called my web service.. got the token and stuck it in the session with LIFERAY_SHARED_.. in my regular portlets i obtained the http session.. this is where my solution stops.. the session attribute it not present.. if I solve this I'll report back..
Posted on 8/8/10 7:34 AM in reply to Dave Godbey.
Hi,

I'm using Liferay 6 and Eclipse. Which is the correct approach to deploy a custom authenticator?

I created a CustomAuthenticator class in my portlet project, which implements Authenticator. I hooked it by editing the portal-ext.properties file (in Liferay\Portal\tomcat-6.0.26\webapps\ROOT\WEB-INF\classes) adding the auth.pipeline.pre property, pointing to my class.
I finally deployed my portlet project on tomcat, but Liferay completely ignores the authenticator and does not even debug into the class.

Any help is appreciated.
Posted on 11/11/10 5:55 AM.
Vishal or Dave,
Did you find the solution?
Thanks,
Kalman
Posted on 1/4/11 11:28 PM in reply to Dave Godbey.
You can use PortalUtil class. to take the session
Posted on 1/19/11 1:07 AM in reply to Dave Godbey.
Hi,

I am looking for SSO solution with Liferay. Looking at the above code, why do we need to add users into Liferay database or ldap? It is ok to add the user name and related information but password.

Have I missed anything here? Please provide any guide lines or documentation related to implement SSO with Liferay.

Thank you.
Posted on 10/31/11 2:42 AM.
@All
I am trying to implement authentication of user through external database.
But not able to achive it. i am new to liferay.
any help or valuable suggestion is most appreciated.

Thank you.
Posted on 11/2/11 12:36 AM in reply to manjula rathnayaka.
Hi,

I developed a CAS. It's working in our production server, but on developers machines, I get a

java.lang.NoClassDefFoundError: com/liferay/portal/service/UserLocalServiceUtil
xxxxx.hooks.auth.EspaceClientsEc­hangesAuth.authenticateByScreenName(MyCustomCASClass.java:43)


The incriminated code is as below :

try {
userDansLiferay = UserLocalServiceUtil
.getUserByScreenName(companyId, screenName); // <=== BOOOM !!!
} catch (Exception e) {
return FAILURE;
}


What could possibly explain this class not found ?

Thank you.
Posted on 8/14/12 8:28 AM in reply to Navnath Gajare.
I am using Liferay 6.1.1 the latest one and I have created the Auto Login - My Scenario is the pass a card number instead of email and then grab the email address from database and return the valid credentials like the following below

if(userName != null && userName.equals("123456") && password.equals("jamikhan"))
{
System.out.println("Valid Request must authenticate");
credentials = new String[3];
credentials[0] = "durrab@dixipay.com";
credentials[1] = password;
credentials[2] = Boolean.TRUE.toString();
return credentials;
}

But Liferay always invalidate that request and gives me an error message that user is not authenticated

I have created it as a hook in liferay 6.1.1 and configured in the portal.properties as auto.login.hooks=myAutoLogin

Need a help

Thanks

Durrab
Posted on 8/26/12 1:21 AM in reply to Mathieu Hicauber.
Can I insert a user with out a password?
Because in my implementation authentication will be handled by a custom authenticator and Liferay does not have access to User password.

My implementation is very similar to ShibbolethAutoLogin and if user does not exist in the DB a new user will be added.So that I want to add a user to Liferay DB without a password. how can I implement this and/or is it possible?
Posted on 3/9/14 12:19 AM.