Implementing custom authentication in DXP

There might be cases when you want to write your own CAS (Custom authentication Service) for authenticating users in Liferay. There are many cases like : authenticating users based on different database, different column. One scenerio is where we want to have a single text box with username, where we need either user enters screen name or email address along with other text box for password. Liferay OOTB supports authentication by Emailaddress, screenName and userId but at one time, you can choose only one of them. 

What is the effort required to use a single text box for both emailAddress and screen name at the same time? There may be many such scenerios.

Liferay support custom authentication mechanism using properties:

Liferay provides one interface "Authenticator". This interface has three methods :

1. authenticateByEmailAddress

2. authenticateByScreenName

3. authenticateByUserId

So when you choose authentication by Email Address, Screen Name and User Id from Liferay control panel, it uses default implementation provided for above interface and if we want to write custom authentication, we need to write our implementation and then plug it into Liferay.

Well, so theory apart. while creating this example, you only need to create one Component class:

1. Create a component class in your module with this component metadata:

@Component(
immediate = true,
property = {
        "key=auth.pipeline.pre"
    },
    service = Authenticator.class
)
 
2. Your Component class should extend Authenticator interface, and provide your implementation for methods:
 
public class CustomAuthenticatorSampleAuthenticator implements Authenticator {
 
@Activate
public void activate() {
Factory<SecurityManager> factory = new IniSecurityManagerFactory(
"classpath:CustomAuthenticatorSampleAuthenticator/userauth.ini");
 
SecurityUtils.setSecurityManager(factory.getInstance());
 
if (_log.isInfoEnabled()) {
_log.info("activate");
}
}
 
@Override
public int authenticateByEmailAddress(
long companyId, String emailAddress, String password,
Map<String, String[]> headerMap,
Map<String, String[]> parameterMap)
throws AuthException {
 
............................
}
 
@Override
public int authenticateByScreenName(
long companyId, String screenName, String password,
Map<String, String[]> headerMap,
Map<String, String[]> parameterMap)
throws AuthException {
 
................................
}
 
@Override
public int authenticateByUserId(
long companyId, long userId, String password,
Map<String, String[]> headerMap,
Map<String, String[]> parameterMap)
throws AuthException {
 
......................................
}
}

In similar way, you can also modify few other out of box DXP functionalities, for example :

Key Interface to implement Description
auth.pipeline.pre Authenticator Custom Authentication 
auth.failure AuthFailure Custom Failed login class implementation
auth.max.failures AuthFailure Custom max number of Failed login class implementation
login.events.pre LifecycleAction Pre login Custom Implementation

Just change your @Component's metdata with above details and you can plug your custom implementation in DXP.