问题
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