Embracing the Messiness in Search of Epic Solutions

Spring Security SAML: Handling IdP’s Public Certificate When Loading Metadata Over HTTPS




By default, when loading IdP’s metadata over HTTPS (ex: https://adfs-server/federationmetadata/2007-06/federationmetadata.xml), Spring Security SAML will perform the trust verification configured in JDK.

However, there are times we do not have direct access to JDK home directory especially if the web apps are hosted on someone else’s JEE or PaaS servers.


To fix this, the IdP’s public certificate can be imported into the app’s keystore instead of JDK’s keystore.

keytool -importcert -file adfs-server.cer -keystore app-keystore.jks -alias "adfs-server"

Then, configure Spring Security SAML to use TLSProtocolConfigurer, which will use all public certificates stored in the app’s keystore as trust anchors for PKIX validation.

public abstract class SecuritySAMLConfig extends WebSecurityConfigurerAdapter {


	// in this case, `app-keystore.jks` contains the app's public/private keys and
	// the imported IdP's public certificate
    public KeyManager keyManager() {
        DefaultResourceLoader loader = new DefaultResourceLoader();
        Resource storeFile = loader.getResource("classpath:app-keystore.jks");
        Map<string, string=""> passwords = new HashMap&lt;&gt;();
        passwords.put("app_alias", "app_password");
        return new JKSKeyManager(storeFile, "app_password", passwords, "app_alias");

    public TLSProtocolConfigurer tlsProtocolConfigurer() {
        return new TLSProtocolConfigurer();

    public ProtocolSocketFactory protocolSocketFactory(KeyManager keyManager) {
        return new TLSProtocolSocketFactory(keyManager, null, "default");

    public Protocol protocol(ProtocolSocketFactory protocolSocketFactory) {
        return new Protocol("https", protocolSocketFactory, 443);

    public MethodInvokingFactoryBean socketFactoryInitialization(Protocol protocol) {
        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
        Object[] args = {"https", protocol};
        return methodInvokingFactoryBean;


Doing so makes the app more portable so that it can be deployed into any JEE or PaaS servers without any problem.


Leave a Reply