NginxProxyTrustedClientCertificateLookup.java
package org.keycloak.services.x509;
import org.jboss.logging.Logger;
import org.keycloak.http.HttpRequest;
import org.keycloak.common.util.PemException;
import org.keycloak.common.util.PemUtils;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
/**
* The NGINX Trusted Provider verify extract end user X.509 certificate sent during TLS mutual authentication,
* verifies it against provided CA the and forwarded in an HTTP header along with a new header ssl-client-verify: SUCCESS.
*
* NGINX configuration must have :
* <code>
* server {
* ...
* ssl_client_certificate path-to-trusted-ca.crt;
* ssl_verify_client on|optional;
* ssl_verify_depth 2;
* ...
* location / {
* ...
* proxy_set_header ssl-client-cert $ssl_client_escaped_cert;
* ...
* }
* </code>
*
* Note that $ssl_client_cert is deprecated, use only $ssl_client_escaped_cert with this implementation
*
* @author <a href="mailto:youssef.elhouti@tailosoft.com">Youssef El Houti</a>
* @version $Revision: 1 $
* @since 01/09/2022
*/
public class NginxProxyTrustedClientCertificateLookup extends AbstractClientCertificateFromHttpHeadersLookup {
private static final Logger log = Logger.getLogger(NginxProxyTrustedClientCertificateLookup.class);
public NginxProxyTrustedClientCertificateLookup(String sslCientCertHttpHeader,
String sslCertChainHttpHeaderPrefix,
int certificateChainLength) {
super(sslCientCertHttpHeader, sslCertChainHttpHeaderPrefix, certificateChainLength);
}
@Override
protected X509Certificate getCertificateFromHttpHeader(HttpRequest request, String httpHeader) throws GeneralSecurityException {
X509Certificate certificate = super.getCertificateFromHttpHeader(request, httpHeader);
if (certificate == null) {
return null;
}
String validCertificateResult = getHeaderValue(request, "ssl-client-verify");
if ("SUCCESS".equals(validCertificateResult)) {
return certificate;
} else {
log.warn("nginx could not verify the certificate: ssl-client-verify: " + validCertificateResult);
return null;
}
}
@Override
protected X509Certificate decodeCertificateFromPem(String pem) throws PemException {
if (pem == null) {
log.warn("End user TLS Certificate is NULL! ");
return null;
}
try {
pem = java.net.URLDecoder.decode(pem, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.error("Cannot URL decode the end user TLS Certificate : " + pem,e);
}
return PemUtils.decodeCertificate(pem);
}
}