All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.quarkus.oidc.runtime.CertChainPublicKeyResolver Maven / Gradle / Ivy

Go to download

Secure your applications with OpenID Connect Adapter and IDP such as Keycloak

There is a newer version: 3.18.0.CR1
Show newest version
package io.quarkus.oidc.runtime;

import java.security.Key;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import org.jboss.logging.Logger;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwx.JsonWebStructure;
import org.jose4j.lang.UnresolvableKeyException;

import io.quarkus.oidc.OidcTenantConfig.CertificateChain;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.security.runtime.X509IdentityProvider;
import io.vertx.ext.auth.impl.CertificateHelper;

public class CertChainPublicKeyResolver implements RefreshableVerificationKeyResolver {
    private static final Logger LOG = Logger.getLogger(OidcProvider.class);
    final Set thumbprints;
    final Optional expectedLeafCertificateName;

    public CertChainPublicKeyResolver(CertificateChain chain) {
        if (chain.trustStorePassword.isEmpty()) {
            throw new ConfigurationException(
                    "Truststore with configured password which keeps thumbprints of the trusted certificates must be present");
        }
        this.thumbprints = TrustStoreUtils.getTrustedCertificateThumbprints(chain.trustStoreFile.get(),
                chain.trustStorePassword.get(), chain.trustStoreCertAlias, chain.getTrustStoreFileType());
        this.expectedLeafCertificateName = chain.leafCertificateName;
    }

    @Override
    public Key resolveKey(JsonWebSignature jws, List nestingContext)
            throws UnresolvableKeyException {

        try {
            List chain = jws.getCertificateChainHeaderValue();
            if (chain == null) {
                LOG.debug("Token does not have an 'x5c' certificate chain header");
                return null;
            }
            if (chain.size() == 0) {
                LOG.debug("Token 'x5c' certificate chain is empty");
                return null;
            }
            LOG.debug("Checking a thumbprint of the root chain certificate");
            String rootThumbprint = TrustStoreUtils.calculateThumprint(chain.get(chain.size() - 1));
            if (!thumbprints.contains(rootThumbprint)) {
                LOG.error("Thumprint of the root chain certificate is invalid");
                throw new UnresolvableKeyException("Thumprint of the root chain certificate is invalid");
            }
            if (expectedLeafCertificateName.isEmpty()) {
                LOG.debug("Checking a thumbprint of the leaf chain certificate");
                String thumbprint = TrustStoreUtils.calculateThumprint(chain.get(0));
                if (!thumbprints.contains(thumbprint)) {
                    LOG.error("Thumprint of the leaf chain certificate is invalid");
                    throw new UnresolvableKeyException("Thumprint of the leaf chain certificate is invalid");
                }
            } else {
                String leafCertificateName = X509IdentityProvider.getCommonName(chain.get(0).getSubjectX500Principal());
                if (!expectedLeafCertificateName.get().equals(leafCertificateName)) {
                    LOG.errorf("Wrong leaf certificate common name: %s", leafCertificateName);
                    throw new UnresolvableKeyException("Wrong leaf certificate common name");
                }
            }
            //TODO: support revocation lists
            CertificateHelper.checkValidity(chain, null);
            if (chain.size() == 1) {
                // CertificateHelper.checkValidity does not currently
                // verify the certificate signature if it is a single certificate chain
                final X509Certificate root = chain.get(0);
                root.verify(root.getPublicKey());
            }
            return chain.get(0).getPublicKey();
        } catch (UnresolvableKeyException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new UnresolvableKeyException("Invalid certificate chain", ex);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy