package org.apereo.cas.support.x509.rest;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.adaptors.x509.authentication.principal.X509CertificateCredential;
import org.apereo.cas.adaptors.x509.util.CertUtils;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.support.rest.DefaultCredentialFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.util.MultiValueMap;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.cert.X509Certificate;
/**
* This is {@link X509CredentialFactory} that attempts to read the contents
* of the request body under {@link #CERTIFICATE} parameter to locate and construct
* X509 credentials. If the request body does not contain a certificate,
* it will then fallback onto the default behavior of capturing credentials.
*
* @author Dmytro Fedonin
* @since 5.1.0
*/
public class X509CredentialFactory extends DefaultCredentialFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(X509CredentialFactory.class);
private static final String CERTIFICATE = "cert";
@Override
public Credential fromRequestBody(final MultiValueMap<String, String> requestBody) {
final String cert = requestBody.getFirst(CERTIFICATE);
LOGGER.debug("Certificate in the request body: [{}]", cert);
if (StringUtils.isBlank(cert)) {
return super.fromRequestBody(requestBody);
}
final InputStream is = new ByteArrayInputStream(cert.getBytes());
final InputStreamSource iso = new InputStreamResource(is);
final X509Certificate certificate = CertUtils.readCertificate(iso);
final X509CertificateCredential credential = new X509CertificateCredential(new X509Certificate[]{certificate});
credential.setCertificate(certificate);
return credential;
}
}