Anyone succesfully used Wss4jSecurityInterceptor for Spring.WS for SAML security with a SAMLCallbackHandler in a Spring Boot application?

人走茶凉 提交于 2021-01-28 09:16:10

问题


Is someone with experience in using Wss4jSecurityInterceptor able to help figuring out if we are doing something wrong regarding a SAMLCallbackHandler for supplying the assertion for the security header of a SOAP call?

Specifically: org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor

Context:

We are building a service bus using Spring Boot + Spring Integration, which needs to be able to consume and produce requests signed with SAML, not in the context of SSO. We have picked Wss4jSecurityInterceptor for validating and signing the SOAP requests with SAML. We are applying the interceptor directly to Spring Webservices and not relying on Spring Integration.

We are currently having problems during signing. We have validation and signatures working but no assertion is applied to outgoing messages. This requires us to use the securement action “SAMLTokenSigned” which requires a CallbackHandler for the interceptor (a SAMLCallbackHandler).

This far we have not been able to find existing implementations or good examples of such a SAMLCallbackHandler. What we have found have been lackluster and lead us onto a long road of “guessing” what the handler is missing through debugging. At this point it seems like we are heading down the wrong road, and that we are missing something. It is not exactly novel work that we are doing.

Setup of the Wss4jSecurityInterceptor looks like shown below.

@Bean
public Wss4jSecurityInterceptor wss4jSecurityInterceptor(){

    Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();

    // The action SAMLTokenSigned requires us to use SAMLCallbackk
    interceptor.setSecurementActions("Signature SAMLTokenSigned");

    interceptor.setSecurementSignatureCrypto(keystoreCrypto());
    interceptor.setSecurementUsername("client");
    interceptor.setSecurementPassword("password");
    interceptor.setSecurementSignatureDigestAlgorithm("http://www.w3.org/2007/05/xmldsig-more#sha3-256");
    interceptor.setSecurementSignatureAlgorithm("http://www.w3.org/2009/xmldsig11#dsa-sha256");

    SAML2CallbackHandler saml2CallbackHandler = new SAML2CallbackHandler(); // implements CallbackHandler
    saml2CallbackHandler.crypto = keystoreCrypto(); // using the same keystore for the issuer
    interceptor.setSecurementSamlCallbackHandler(saml2CallbackHandler);

    // we ignore validationActions for now. e.g. interceptor.setValidationActions("Signature");

    return interceptor;
}

public Crypto keystoreCrypto(){
    CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();

    try{
        cryptoFactoryBean.setKeyStoreLocation( new ClassPathResource("saml-keystore.jks"));
        cryptoFactoryBean.setKeyStorePassword("password");
        return cryptoFactoryBean.getObject();
    }
    catch(Exception e){}

    return null;
}

Our SAML2Callback handler is heavily inspired by https://github.com/jaminh/spring-saml-example-war/blob/master/src/test/java/org/apache/ws/security/common/SAML2CallbackHandler.java but we had to deal with libraries we could not find on maven-repositories, which gave a series of small issues. I can provide our version upon request, but it is somewhat of a mess.

While I do not expect it to provide much, here is the Stacktrace for the exception that is thrown for the code at the point of writing:

Original Exception was org.apache.wss4j.common.ext.WSSecurityException: No certificates were found for SAML signature
    at org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor.secureMessage(Wss4jSecurityInterceptor.java:577) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    at org.springframework.ws.soap.security.AbstractWsSecurityInterceptor.handleResponse(AbstractWsSecurityInterceptor.java:157) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.triggerHandleResponse(MessageDispatcher.java:371) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:239) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:176) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:89) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:61) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:293) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: org.apache.wss4j.common.ext.WSSecurityException: Error when signing the SAML token: 
    at org.apache.wss4j.dom.action.SAMLTokenSignedAction.execute(SAMLTokenSignedAction.java:133) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.apache.wss4j.dom.handler.WSHandler.doSenderAction(WSHandler.java:238) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.springframework.ws.soap.security.wss4j2.Wss4jHandler.doSenderAction(Wss4jHandler.java:63) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    at org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor.secureMessage(Wss4jSecurityInterceptor.java:574) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    ... 45 common frames omitted
Caused by: org.apache.wss4j.common.ext.WSSecurityException: No certificates were found for SAML signature
    at org.apache.wss4j.dom.saml.WSSecSignatureSAML.prepare(WSSecSignatureSAML.java:258) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.apache.wss4j.dom.saml.WSSecSignatureSAML.build(WSSecSignatureSAML.java:110) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.apache.wss4j.dom.action.SAMLTokenSignedAction.execute(SAMLTokenSignedAction.java:125) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    ... 48 common frames omitted

The same expectation for information about keystore, but maybe it could be relevant:

  • Generated with keytool (I do not recall the command unfortunately)
  • Public Key type and size: DSA 2048 bits Signature Algorithm:
  • SHA256WITHDSA Fingerprint SHA-1
  • 37:E8:E0:B7:DD:7E:7A:33:43:F8:9D:06:6D:20:1E:BE:B7:63:3A:B9

来源:https://stackoverflow.com/questions/61520480/anyone-succesfully-used-wss4jsecurityinterceptor-for-spring-ws-for-saml-security

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!