Here is one that uses Basic Authentication:
package be.aquafin.bpm.custom;
import static org.camunda.bpm.engine.authorization.Permissions.ACCESS;
import static org.camunda.bpm.engine.authorization.Resources.APPLICATION;
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.DatatypeConverter;
import org.camunda.bpm.BpmPlatform;
import org.camunda.bpm.engine.AuthorizationService;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.identity.Group;
import org.camunda.bpm.engine.identity.Tenant;
import org.camunda.bpm.webapp.impl.security.SecurityActions;
import org.camunda.bpm.webapp.impl.security.SecurityActions.SecurityAction;
import org.camunda.bpm.webapp.impl.security.auth.Authentication;
import org.camunda.bpm.webapp.impl.security.auth.AuthenticationFilter;
import org.camunda.bpm.webapp.impl.security.auth.Authentications;
import org.camunda.bpm.webapp.impl.security.auth.UserAuthentication;
import java.util.logging.Logger;
/**
- Replaces {@link AuthenticationFilter} by an extension which can auto-logon a
- user by using Basic Authentication
-
*/
public class LoginAuthenticationFilter implements Filter {
private static final String[] APPS = new String[] { "cockpit", "tasklist" };
private static final String APP_MARK = "/app/";
private static final String CAMUNDA_ADMIN_GROUP = "BPM-ADMIN";
private static final Logger logger = Logger.getLogger(AuthenticationFilter.class.getName());
public void init(FilterConfig arg0) throws ServletException {
}
public void destroy() {
}
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest req = (HttpServletRequest) request;
// get authentication from session
Authentications authentications = Authentications.getFromSession(req.getSession());
// This function is added to the normal AuthenticationFilter
setAutoLoginAuthentication(request, response, authentications);
// set current authentication to the one restored from session (maybe
// auto login was added)
Authentications.setCurrent(authentications);
try {
SecurityActions.runWithAuthentications(new SecurityAction<Void>() {
public Void execute() {
try {
chain.doFilter(request, response);
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
}, authentications);
} finally {
Authentications.clearCurrent();
// store updated authentication object in session for next request
Authentications.updateSession(req.getSession(), authentications);
}
}
/**
* Reads the auto-login-username from the URL parameters and create an
* {@link Authentication} for it containing its groups, tenants and
* authorized apps.
*
*/
protected void setAutoLoginAuthentication(final ServletRequest request, ServletResponse response, Authentications authentications) throws ServletException {
boolean isAdmin = false;
String username = null;
final HttpServletRequest req = (HttpServletRequest) request;
final ProcessEngine engine = getEngine();
Principal principal = req.getUserPrincipal();
if (principal != null && principal.getName() != null && !principal.getName().isEmpty()) {
username = principal.getName();
logger.info("principal username = " + username);
username = username.toUpperCase();
} else {
String authHeader = req.getHeader("Authorization");
if (authHeader != null && !authHeader.isEmpty()) {
String encodedValue = authHeader.split(" ")[1];
byte[] decoded = DatatypeConverter.parseBase64Binary(encodedValue);
String decodedString = "";
try {
decodedString = new String(decoded, "UTF-8");
} catch (Exception ex) {
throw new RuntimeException("Kan basic authentication string niet decoderen", ex);
}
username = decodedString.split(":")[0];
logger.info("basic authentication username = " + username);
username = username.toUpperCase();
String password = decodedString.split(":")[1];
//AUTHENTICATION TO CAMUNDA (AD)
if (!isAuthenticated(engine, username, password)) {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
try {
unauthorized(httpServletResponse, "Foute username of paswoord!");
} catch (Exception ex) {
throw new RuntimeException("sending unauthorized response failed");
}
}
else {
logger.info("username " + username+" is authenticated");
}
}
}
if (username != null && !username.isEmpty()) {
// if already in the list of logged in users - nothing to do
Authentication authentication = authentications.getAuthenticationForProcessEngine(engine.getName());
if (authentication != null) {
if (authentication.getName().equals(username)) {
logger.info(" username = " + username+ " is reeds ingelogd");
return;
}
}
else {
logger.info("username " + username+" geen authenticatie record gevonden");
}
List<String> groupIds = new ArrayList<String>();
String url = req.getRequestURL().toString();
logger.info("url = "+url);
String appname = getApp(url);
if (appname != null) {
logger.info("appname " + appname);
if (engine != null) {
final List<Group> groupList = engine.getIdentityService().createGroupQuery().groupMember(username)
.list();
// transform into array of strings:
for (Group group : groupList) {
groupIds.add(group.getId());
logger.info("group.getId() " + group.getId());
if (group.getId().equals(CAMUNDA_ADMIN_GROUP)) {
isAdmin = true;
logger.info(" username = " + username+ " is in ADMIN group");
}
}
}
AuthorizationService authorizationService = engine.getAuthorizationService();
List<String> tenantIds = getTenantsOfUser(engine, username);
// check user's app authorizations by iterating of
// list of apps and ask if permitted
HashSet<String> authorizedApps = new HashSet<String>();
if (engine.getProcessEngineConfiguration().isAuthorizationEnabled()) {
for (String application : APPS) {
if (authorizationService.isUserAuthorized(username, groupIds, ACCESS, APPLICATION,
application)) {
logger.info(" username = " + username+ " heeft toegang tot " + application);
authorizedApps.add(application);
}
}
if (isAdmin)
authorizedApps.add("admin");
} else {
Collections.addAll(authorizedApps, APPS);
authorizedApps.add("admin");
}
if (authorizedApps.contains(appname)) {
// create new authentication object to store
// authentication
UserAuthentication newAuthentication = new UserAuthentication(username, engine.getName());
newAuthentication.setGroupIds(groupIds);
newAuthentication.setTenantIds(tenantIds);
newAuthentication.setAuthorizedApps(authorizedApps);
// and add the new logged in user
authentications.addAuthentication(newAuthentication);
}
}
else {
logger.info("geen app in url?");
}
}
}
protected boolean isAuthenticated(ProcessEngine engine, String userName, String password) {
return engine.getIdentityService().checkPassword(userName, password);
}
/**
* copied from
* org.camunda.bpm.webapp.impl.security.auth.UserAuthenticationResource
*/
protected List<String> getGroupsOfUser(ProcessEngine engine, String userId) {
List<Group> groups = engine.getIdentityService().createGroupQuery().groupMember(userId).list();
List<String> groupIds = new ArrayList<String>();
for (Group group : groups) {
groupIds.add(group.getId());
}
return groupIds;
}
private String getApp(String url) {
String app = null;
int index = url.indexOf(APP_MARK);
if (index >= 0) {
String urlLastPart = url.substring(index + APP_MARK.length());
index= urlLastPart.indexOf("/");
if (index >= 0) {
app = urlLastPart.substring(0,index);
}
else {
app = urlLastPart;
}
}
return app;
}
protected List<String> getTenantsOfUser(ProcessEngine engine, String userId) {
List<Tenant> tenants = engine.getIdentityService().createTenantQuery().userMember(userId)
.includingGroupsOfUser(true).list();
List<String> tenantIds = new ArrayList<String>();
for (Tenant tenant : tenants) {
tenantIds.add(tenant.getId());
}
return tenantIds;
}
private ProcessEngine getEngine() {
return BpmPlatform.getDefaultProcessEngine();
}
private void unauthorized(HttpServletResponse response, String message) throws IOException {
response.setHeader("WWW-Authenticate", "Basic realm=Protected");
response.sendError(401, message);
}
private void unauthorized(HttpServletResponse response) throws IOException {
unauthorized(response, "Unauthorized");
}