Custom SSO Solution

Our built-in solutions may not fit your needs - but you may implement your own Single Sign-on solution by implementing a Tomcat Valve and register this valve in context.xml. A valve is something which will be executed for every request sent to the Axon Ivy Engine.

This is our Single Sign-on valve. Use it as template and adapt it your needs:

package ch.ivyteam.ivy.webserver.security;

import java.io.IOException;
import java.security.Principal;

import javax.servlet.ServletException;

import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.commons.lang3.StringUtils;

import ch.ivyteam.api.PublicAPI;

/**
 * <p><strong style="color:red"> Only use this Valve if you exclusively access Axon Ivy over the WebApplication Firewall.
 * Otherwise this will be a security hole.</strong></p>
 *
 * This Valve is useful if Axon Ivy is protected by a WebApplication Firewall (WAF) with an integrated
 * Identity and Access Management (IAM). Those systems will authenticate and authorize users.
 * The identified user is then sent from the WAF to Axon Ivy using a HTTP request header.
 *
 * <pre>
 * WebBrowser {@literal ==>} WAF {@literal ==>} Axon Ivy
 *
 *                 ^          |
 *                 |          |
 *                 v          v
 *
 *                IAM {@literal ==>} Active Directory
 * </pre>
 * @since 6.6
 */
@PublicAPI
public class SingleSignOnValve extends ValveBase {
  public static final String DEFAULT_USER_NAME_HEADER = "user";

  private String userNameHeader = DEFAULT_USER_NAME_HEADER;

  public SingleSignOnValve() {
    super(true);
  }

  public void setUserNameHeader(String headerName) {
    this.userNameHeader = headerName;
  }

  public String getUserNameHeader() {
    return userNameHeader;
  }

  /**
   * This implementation reads the user from the HTTP header field user.
   *
   * @see org.apache.catalina.Valve#invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response)
   */
  @Override
  public void invoke(Request request, Response response) throws IOException, ServletException {
    String userName = request.getHeader(userNameHeader);
    if (StringUtils.isNotBlank(userName)) {
      Principal principal = createUserPrincipal(userName);
      request.setUserPrincipal(principal);
    }
    getNext().invoke(request, response);
  }

  private static Principal createUserPrincipal(String userName) {
    return new UserPrincipal(userName);
  }

  private static final class UserPrincipal implements Principal {
    private final String userName;

    UserPrincipal(String userName) {
      this.userName = userName;
    }

    @Override
    public String getName() {
      return userName;
    }
  }
}