All the info I found about that where too ambiguous, not useful by itself. Something like “make an Authentication Service Implementation by yourself”.
So I searched a lot and found some way to make it working. I write the steps here:
(Disclaimer: Use at your own risk, I’m not responsible for any problem/damage direct or indirect.)
1-Create some admins users on Bonita, with exactly the same samAccountName that you have on your Active Directory.
Once you enable AD/LDAP authentication all your users will validate against the Active Directory. Maybe you can tweak the source code below to allow some privileged accounts to be in local Bonita DB.
So make sure you can connect after you link to AD.
2-Download this source code, save it as “JAASAuthenticationServiceImpl.java”
Disclaimer: The source code isn’t mine, it’s taken from https://github.com/stephanel/BonitaBPM-AuthServices/tree/master/src/in/stephanelep/bonita/auth , with some minor tweaks.
It seems to work.
package org.bonitasoft.engine.authentication.impl;
import java.io.Serializable;
import java.util.Map;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.*;
import org.bonitasoft.engine.authentication.AuthenticationConstants;
import org.bonitasoft.engine.authentication.AuthenticationException;
import org.bonitasoft.engine.authentication.GenericAuthenticationService;
import org.bonitasoft.engine.log.technical.TechnicalLogSeverity;
import org.bonitasoft.engine.log.technical.TechnicalLoggerService;
import org.bonitasoft.engine.sessionaccessor.STenantIdNotSetException;
import org.bonitasoft.engine.sessionaccessor.SessionAccessor;
public class JAASAuthenticationServiceImpl implements GenericAuthenticationService {
private TechnicalLoggerService logger;
private SessionAccessor sessionAccessor;
public JAASAuthenticationServiceImpl(final TechnicalLoggerService logger, final SessionAccessor sessionAccessor) {
this.logger = logger;
this.sessionAccessor = sessionAccessor;
this.logger.log(this.getClass(), TechnicalLogSeverity.DEBUG, "AD/LDAP Initialization");
}
@Override
public String checkUserCredentials(final Map<String, Serializable> credentials) throws AuthenticationException {
long tenantId;
LoginContext lc;
final String authUsername = String.valueOf(credentials.get(AuthenticationConstants.BASIC_USERNAME));
final String authPassword = String.valueOf(credentials.get(AuthenticationConstants.BASIC_PASSWORD));
String username = authUsername;
try {
tenantId = this.sessionAccessor.getTenantId();
lc = new LoginContext("BonitaAuthentication-"+tenantId, new CallbackHandler(){
public void handle(Callback[] callbacks) {
for(int i = 0; i < callbacks.length; i++) {
if(callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback)callbacks[i];
nc.setName(authUsername);
}
else if(callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback)callbacks[i];
pc.setPassword(authPassword.toCharArray());
}
}
}
});
lc.login();
logger.log(this.getClass(), TechnicalLogSeverity.DEBUG, "AD/LDAP: Auth success for user "+username);
return username;
}
catch (LoginException e) {
logger.log(this.getClass(), TechnicalLogSeverity.ERROR, "AD/LDAP: Auth failure for user "+username+": "+e.getMessage());
throw new AuthenticationException();
}
catch (STenantIdNotSetException e) {
logger.log(this.getClass(), TechnicalLogSeverity.ERROR, "AD/LDAP: Auth failure for user "+username+": "+e.getMessage());
throw new AuthenticationException();
}
catch(Exception e) {
logger.log(this.getClass(), TechnicalLogSeverity.ERROR, "AD/LDAP: Unknown exception "+e.getClass().toString()+": "+e.getMessage());
}
return null;
}
}
3-Then compile it with javac. IMPORTANT! You must compile it with these parameters:
javac -g:vars -cp bonita-server-6.5.1.jar JAASAuthenticationServiceImpl.java
Without the -g:vars the class won’t work. You must have the bonita-server-6.X.X.jar in the same folder, or correctly target it on the -cp parameter.
I used JDK 6 to compile it, just because I saw original bonitasoft classes used it.
4-Then create a temporary folder structure like this: org\bonitasoft\engine\authentication\impl
And place the compiled JAASAuthenticationServiceImpl.class and JAASAuthenticationServiceImpl$1.class inside the “impl” folder.
Zip the structure, you must have a zip with the same structure as I stated, with the two class files on the impl folder.
5-Rename the zip file to “JAASAuthenticationServiceImpl.jar” and place it on apache-tomcat/webapps/bonita/WEB-INF/lib
You can delete this folder structure, it’s only needed to create the jar with the correct folders that matches the package name.
I attach the compiled jar I used, but I encourage you to compile by yourself, it’s really easy to do (you just need a JDK).
Compiled JAASAuthenticationServiceImpl.jar
With that you can use the official document: http://documentation.bonitasoft.com/active-directoryldap-authentication-0
Just don’t use the class=“com.bonitasoft.engine.authentication.impl.JAASGenericAuthenticationServiceImpl”
You must user class=“org.bonitasoft.engine.authentication.impl.JAASGenericAuthenticationServiceImpl” with an starting org. instead of com. because it’s the package I used on the source code.
You can use the original package name that Stephane used on the source code (and creating the folder structure to comply the package name), I just wanted to keep all auth implementations on the same package
I configured exactly that to enable AD on Apache-Tomcat:
AD_1- On setenv.sh (or setenv.bat in Windows) I enabled this line:
SECURITY_OPTS=“-Djava.security.auth.login.config=${CATALINA_HOME}/conf/jaas-standard.cfg”
mine had a # before, I uncommented it.
And modify the CATALINA_OPS line to add this option:
CATALINA_OPTS=“${CATALINA_OPTS} ${BONITA_HOME} ${SECURITY_OPTS} ${DB_OPTS} ${BTM_OPTS} -Dfile.encoding=UTF-8 -Xshare:auto -Xms2048m -Xmx2048m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError”
Note, the other CATALINA_OPS are dependant on your environment, don’t copy mine. Only add the ${SECURITY_OPTS} after ${BONITA_HOME}
On windows it’s something like that:
set SECURITY_OPTS=“-Djava.security.auth.login.config=%CATALINA_HOME%\conf\jaas-standard.cfg”
set CATALINA_OPTS=%CATALINA_OPTS% %BONITA_HOME% %SECURITY_OPTS% %DB_OPTS% %BTM_OPTS% -Dfile.encoding=UTF-8 -Xshare:auto -Xms1024m -Xmx1024m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError
AD_2- Set contents of ${CATALINA_HOME}/conf/jaas-standard.cfg
BonitaAuthentication-1 {
com.sun.security.auth.module.LdapLoginModule REQUIRED
userProvider=“ldap://dc1.domain.com:389/dc=domain,dc=com”
authIdentity=“{USERNAME}@domain.com”
userFilter=“(&(objectClass=user)(samAccountName={USERNAME})(!(userAccountControl:1.2.840.113556.1.4.803:=18)))”
useSSL=false
debug=false;
};
Replace dc1.domain.com with your real domain controller (you can also use an IP). My users login with their logon name, they don’t need to add the @domain.com.
Replace domain.com for your real domain name, both on userProvider and authIdentity.
My userFilter searches only actives user accounts with samAccountName = Bonita username.
I search on the whole AD forest, if you want to narrow the search change the userProvider and add something like:
check for the correct use of cn= or ou= I always mix them.
userProvider=“ldap://dc1.domain.com:389/cn=users,dc=domain,dc=com”
If you have several DC’s, I think you can add redundancy with :
userProvider=“ldap://dc1.domain.com:389/dc=domain,dc=com ldap://dc2.domain.com:389/dc=domain,dc=com”
Note: If your users aren’t allowed to search in AD you must add these two lines inside the BonitaAuthentication-1:
java.naming.security.principal="user@domain.com"
java.naming.security.credentials=“yourpassword”
Use some AD user with delegated privileges to make searches and read person objects, DO NOT USE an administrator AD account.
AD_3- Go to apache-tomcat/bonita/server/tenants//conf/services/
Make a backup of the file: cfg-bonita-authentication-impl.xml , name it cfg-bonita-authentication-impl.xml.backup for example.
Edit cfg-bonita-authentication-impl.xml and write this:
<bean id="authenticationService" class="org.bonitasoft.engine.authentication.impl.JAASAuthenticationServiceImpl" >
<constructor-arg index="0" name="logger" ref="tenantTechnicalLoggerService" />
<constructor-arg index="1" name="sessionAccessor" ref="sessionAccessor" />
</bean>
AD_4- Restart Tomcat server and watch log files for errors. If something fails check names on config files (names are case sensitives) and use debug=true on jass-standard.cfg file, and restart