package de.otto.edison.togglz.authentication; import com.unboundid.ldap.sdk.*; import com.unboundid.ldap.sdk.extensions.StartTLSExtendedRequest; import com.unboundid.util.ssl.SSLUtil; import de.otto.edison.togglz.configuration.TogglzLdapProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; import javax.servlet.Filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.Optional; import static org.springframework.http.HttpHeaders.WWW_AUTHENTICATE; import static org.springframework.http.HttpStatus.UNAUTHORIZED; import static org.springframework.util.StringUtils.isEmpty; public class LdapAuthenticationFilter implements Filter { private static Logger LOG = LoggerFactory.getLogger(LdapAuthenticationFilter.class); private final TogglzLdapProperties ldapProperties; public LdapAuthenticationFilter(final TogglzLdapProperties ldapProperties) { this.ldapProperties = ldapProperties; } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; if (isEmpty(httpRequest.getHeader("Authorization"))) { unauthorized(httpResponse); } else { Optional<Credentials> credentials = Credentials.readFrom(httpRequest); if (!ldapProperties.isValid() || !credentials.isPresent() || !ldapAuthentication(credentials.get())) { unauthorized(httpResponse); } else { chain.doFilter(request, response); } } } private void unauthorized(HttpServletResponse httpResponse) { httpResponse.addHeader(WWW_AUTHENTICATE, "Basic realm=Authorization Required"); httpResponse.setStatus(UNAUTHORIZED.value()); } private boolean ldapAuthentication(Credentials credentials) { boolean authOK = false; LDAPConnection ldapConnection = null; try { SSLUtil sslUtil = new SSLUtil(); SSLContext context = sslUtil.createSSLContext(); ExtendedRequest extRequest = new StartTLSExtendedRequest(context); ldapConnection = new LDAPConnection(ldapProperties.getHost(), ldapProperties.getPort()); ldapConnection.processExtendedOperation(extRequest); BindResult bindResult = ldapConnection.bind( ldapProperties.getRdnIdentifier() + "=" + credentials.getUsername() + "," + ldapProperties.getBaseDn(), credentials.getPassword() ); if (bindResult.getResultCode().equals(ResultCode.SUCCESS)) { LOG.info("Login successful: " + credentials.getUsername()); authOK = true; } else { LOG.info("Access denied: " + credentials.getUsername()); } } catch (LDAPException | GeneralSecurityException e) { LOG.info("Authentication error: ", e); } finally { if (ldapConnection != null) { ldapConnection.close(); } } return authOK; } }