Single sign-on AuthenticationGenerally speaking, enterprise applications encompass multiple line-of-business (LOB) applications. These LOB applications are primarily accessed via a common authentication gateway module i.e. by implementing or making use of a single sign-on authentication. Is it similar in Bonita application too? Let’s find out, along with this, we will also figure out the process of integrating an existing SSO authentication module to Bonita application.

SSO Authentication

When the Bonita application is added to an existing enterprise application stack, Bonita users are authenticated via an existing SSO authentication module, instead of Bonita application’s login module. After successful authentication by the SSO module, users are directed to the Bonita application’s home page without seeking any additional login credentials.

Customer Authentication Module

Here’s a high-level process to integrate the customer authentication module in Bonita. In the example cited for reference, we have utilized Bonita 6.3.1 and Oracle Access Manager (OAM) for the authentication module. Generally speaking, the Bonita application is accessed via an enterprise dashboard, where authentication is performed against OAM service. The below diagram clearly illustrates the SSO authentication mechanism employed by the Bonita application.

Image depicting SSO Authentication in Bonita

Implementing SSO Authentication 

Implementing SSO Authentication in the Bonita application is a fairly simple process. The implementation process has been divided into five simple steps to make the users easily understand the concept of SSO Authentication in Bonita.

  1. Create a standalone Java project with Bonita dependencies.
  2. Implement SSOIntegrationFilter logic to validate the authentication cookie/token as per respective SSO mechanism, which is followed by the custom authentication module.
  3. Implement logic to create APISession for trusted users.
  4. Build a JAR and add to the Bonita classpath.
  5. Define SSOIntegrationFilter configuration into Bonita web.xml.

Step 1 – Creating a standalone Java project with Bonita dependencies

The first step is to create a standalone maven project and define all the required dependencies in the pom.xml file. Below is the code, which would help you achieve this activity:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.company.bonita6</groupId>
 <artifactId>bonita-dashboard-sso</artifactId>
 <version>1.0</version>
 <packaging>jar</packaging>

 <properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 <bonita.version>6.3.1</bonita.version>
 <spring.version>3.1.1.RELEASE</spring.version>
 <spring.security.version>3.1.0.RELEASE</spring.security.version>
 <java.version>1.6</java.version>
 </properties>

 <dependencies>
 <dependency>
 <groupId>com.bonitasoft.engine</groupId>
 <artifactId>bonita-server-sp</artifactId>
 <version>${bonita.version}</version>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>org.bonitasoft.console.common.server</groupId>
 <artifactId>common-server-sp</artifactId>
 <version>${bonita.version}</version>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>com.bonitasoft.engine</groupId>
 <artifactId>bonita-common-sp</artifactId>
 <version>${bonita.version}</version>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>com.bonitasoft.engine</groupId>
 <artifactId>bonita-client-sp</artifactId>
 <version>${bonita.version}</version>
 <scope>provided</scope>
 </dependency>
 </dependencies>
</project>

Step 2 – Servlet Filter Implementation

Subsequently, implement a servlet filter to ensure that each request has a valid SSO cookie/token. Bonita users also need to ensure that the token/cookie has not expired. As mentioned earlier, the process requires invoking the OAM web service to validate a cookie/token. Here’s the servlet filter implementation code:

public class CustomSSOIntegrationFilter implements Filter {
public void doFilter(ServletRequest servletRquest,
 ServletResponse servletResponse, FilterChain chain)
 throws IOException, ServletException {

 HttpServletRequest httpRequest = (HttpServletRequest) servletRquest;
 HttpSession httpSession = httpRequest.getSession();

 /**
 * Create Bonita session, if the user is a trusted user and session not yet
 * available.
 */
 if (httpSession.getAttribute(BONITA_SESSION) == null) {

 String ssoCookie = retrieveSSOCookie(httpRequest);

 if (ssoCookie == null || ssoCookie.trim().length() == 0) {
 /**
 * This is to ensure that if Bonita portal is accessed
 * directly (in case of Admin, Install, etc.) user will be
 * redirected to login page and SSO is ignored.
 */
 if (LOGGER.isLoggable(Level.WARNING)) {
 LOGGER.log(
 Level.WARNING,
 " ssoCookie is not available in the request, the user will be redirected to Bonita login page.");
 }

 } else {
 if (LOGGER.isLoggable(Level.FINE)) {
 LOGGER.log(Level.FINE, "Found ssoCookie in Request....."
 + ssoCookie);
 }
 String trustedUser = new OAMServiceStub(OAM_SERVICE_URL).authenticateSSOCookie(ssoCookie);

 if (trustedUser == null || trustedUser.trim().length() == 0) {
 new InvalidUserException(
 "Invalid User credentials. Please login with valid user credentials.");
 }

 BonitaSessionCreator.getInstance().createSession(httpRequest,
 trustedUser);
 }
 }

 chain.doFilter(httpRequest, servletResponse);

 }
private String retrieveSSOCookie(final HttpServletRequest request) {
 String ssoCookie = "";
 Cookie cookies[] = request.getCookies();
 if (cookies != null) {
 for (int i = 0; i < cookies.length; i++) {
 if (cookies[i].getName().equalsIgnoreCase(SSO_COOKIE)) {
 ssoCookie = cookies[i].getValue();

 }
 }

 }
 return ssoCookie;
 }
}

Step 3 – Create APISession

Once the SSO authentication module successfully validates a cookie/token, the next step is to create an APISession using Bonita application’s login API. Please make a note, when an APISession is available in the request, Bonita does not redirect users to the login page till the user session is valid.

public class BonitaSessionCreator {

 private static final Logger LOGGER = Logger
 .getLogger(BonitaSessionCreator.class.getName());

 private static final String BONITA_SESSION = "apiSession";

 private static BonitaSessionCreator sessionCreator = null;

 public synchronized static BonitaSessionCreator getInstance() {
 if (sessionCreator == null) {
 sessionCreator = new BonitaSessionCreator();
 }
 return sessionCreator;
 }

 public void createSession(HttpServletRequest httpRequest, String trustedUser)
 throws ServletException {
 HttpSession httpSession = httpRequest.getSession();
 /**
 * trusted user name is considered as default password to log onto
 * bonita. Or we can obtain the password form SSO module too.
 */
 String password = trustedUser.toLowerCase();
 try {
 loginIntoBonita(trustedUser, password, httpSession);
 } catch (LoginException le) {
 if (LOGGER.isLoggable(Level.WARNING)) {
 LOGGER.log(Level.WARNING,
 "Unable to login into Bonita for trusted user = "
 + trustedUser);
 }
throw new ServletException(e);

 }
 }

 private APISession loginIntoBonita(String trustedUser, String password,
 HttpSession httpSession) throws ServletException, LoginException {
 APISession apiSession = null;
 try {
 LoginAPI loginAPI = TenantAPIAccessor.getLoginAPI();
 apiSession = loginAPI.login(trustedUser, password);
 httpSession.setAttribute(BONITA_SESSION, apiSession);
 if (LOGGER.isLoggable(Level.FINE)) {
 LOGGER.log(Level.FINE, "Bonita session created for the user= "
 + trustedUser);
 }
 } catch (LoginException le) {
 throw le;
 } catch (Exception e) {
 if (LOGGER.isLoggable(Level.SEVERE)) {
 LOGGER.log(
 Level.SEVERE,
 "Error while creating bonita session for the user = "
 + trustedUser + ", " + password
 + e.getMessage(), e);
 }
 throw new ServletException(
 "Unable login into Bonita Portal. Please contact System Administrator. "
 + e.getMessage());
 }
 return apiSession;
 }

 }

Step 4 – Building the Bonita Java Project

This is an important step, execute the maven install/build command to build a standalone Bonita Java project .jar file. Here’s the code snippet, which would help you accomplish this activity:

<Bonita_Home>/webapps/bonita6/WEB-INF/lib/bonita-custom-sso-1.0.jar

Step 5 – SSOIntegrationFilter Configuration into Bonita web.xml

The final step is to add SSOIntegrationFilter configuration in the Bonita web.xml file. Add the below filter mapping element in the web.xml file, which can be located in the path mentioned below.

</pre>
<h6><span style="color: #000000;">Add the below filter definition before “InternalSSOFilter” filter definition</span></h6>
<pre>
 <!-- Custom SSO filter definition-->
<filter>
 <filter-name>CustomSSOIntegrationFilter</filter-name>
 <filter-class>com.company.bonita6.sso.filter.CustomSSOIntegrationFilter</filter-class>
</filter>
Add the below filter mapping before “AuthenticationFilter” filter mapping:
<!-- Custom SSO filter mapping-->
 <filter-mapping>
 <filter-name>CustomSSOIntegrationFilter</filter-name>
 <url-pattern>/portal/BonitaConsole.html</url-pattern>
 </filter-mapping>
 <filter-mapping>
 <filter-name>CustomSSOIntegrationFilter</filter-name>
 <url-pattern>/portal/homepage</url-pattern>
 </filter-mapping>
Add the below filter mapping before “ShutdownListener” listener:
<filter-mapping>
 <filter-name>AuthorizationFilter</filter-name>
 <url-pattern>/portal/BonitaConsole.html</url-pattern>
 </filter-mapping>
 <filter-mapping>
 <filter-name>AuthorizationFilter</filter-name>
 <url-pattern>/portal/homepage</url-pattern>
</filter-mapping>

Conclusion

The above guidance would certainly help Bonita users to integrate existing SSO Authentication module to Bonita application. Although, users are authenticated via the SSO authentication module, Bonita application still requires user data to be present in the Bonita user tables in journal schema. The Bonita application performs workflow/task authorization based on a users membership level. Nevertheless, there are several other ways to sync users information from LDAP/AD into Bonita Journal, which is an altogether different topic and can be discussed in a separate blog.