Customizing the Liferay Connector to SAML 2.0 App

The Liferay Connector to SAML 2.0 enables Liferay to be configured as an SP and an iDP. When using liferay as a service provider (and a non-Liferay IDP), only a few user attributes can be configured out-of-the-box. Many a times, it is required to update additional user attributes like gender, DOB etc based on the business requirements, but any additional attribute you pass in the SAML assertion from the IDP gets ignored.

We can achieve this by adding a bit of customization to the existing app.

Solution:

Lets say we want the user gender to be updated and we have added an additional attribute mapping to the SAML configuration:

http://wso2.org/claims/gender=gender

Since SAML plugin is an EE only application, the binary files are not available publicly. So the first step would be to extract the jar files from the .lpkg files into a repository used for your workspace or you can simply move the jar file inside your module. There is no need to extract all the binary files from the lpkg, only the ones you need to satisfy your build dependencies.

For our purpose, we will need only the com.liferay.saml.opensaml.integration and com.liferay.saml.persistence.api binaries from the SAML API .lpkg file.

Once the jar files are extracted, update the build.gradle file to refer the repository wherein the jar file resides and add a compile time dependency for the binaries.

// I have copied the jars to a 'lib' folder inside my osgi module

repositories {
   flatDir {
       dirs 'lib'
   }
}

dependencies {

compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"

compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"


compile group: 'com.liferay', name: 'com.liferay.saml.opensaml.integration', version: '2.0.29'

compile group: 'com.liferay', name: 'com.liferay.saml.persistence.api', version: '2.1.1'

}

Create a component class registering the UserResolver service and having a higher service ranking. You can take the bulk of the code from the DefaultUserResolver.java file from  SAML source code and add the below customization to  the addUser method to fetch the gender value.

@Component(

immediate = true,  property = "service.ranking:Integer=100",

service = UserResolver.class

)

public class CustomUserResolver implements UserResolver {

...
protected User addUser(long companyId, Map<String, List<Serializable>> attributesMap, ServiceContext serviceContext)
            throws PortalException {
         
          String gender = getValueAsString("gender", attributesMap);
          ...

       }


}

For resolving any additional dependencies, you can refer the build.gradle  from github.

https://github.com/liferay/liferay-portal/blob/be1363857d65884c50a7cbe14b0365b69486e03f/modules/dxp/apps/saml/saml-opensaml-integration/build.gradle

Build and deploy your module, and you are good to go!