SWS-955 - Add method for configuring SAML callback.

This commit is contained in:
Jamin Hitchcock
2016-04-06 20:50:32 -05:00
committed by Greg Turnquist
parent 05092c3333
commit e34fb937d1
5 changed files with 138 additions and 1 deletions

View File

@@ -143,6 +143,8 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
private boolean securementUseDerivedKey;
private CallbackHandler samlCallbackHandler;
// Allow RSA 15 to maintain default behavior
private boolean allowRSA15KeyTransportAlgorithm = true;
@@ -373,6 +375,15 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
public void setSecurementUseDerivedKey(boolean securementUseDerivedKey) {
this.securementUseDerivedKey = securementUseDerivedKey;
}
/**
* Sets the SAML Callback used for generating SAML tokens.
*
* @param samlCallback
*/
public void setSecurementSamlCallbackHandler(CallbackHandler samlCallbackHandler) {
this.samlCallbackHandler = samlCallbackHandler;
}
/** Sets the server-side time to live */
public void setValidationTimeToLive(int validationTimeToLive) {
@@ -595,7 +606,11 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
requestData.setWssConfig(wssConfig);
messageContext.setProperty(WSHandlerConstants.TTL_TIMESTAMP, Integer.toString(securementTimeToLive));
if (this.samlCallbackHandler != null) {
messageContext.setProperty(WSHandlerConstants.SAML_CALLBACK_REF, this.samlCallbackHandler);
}
// allow for qualified password types for .Net interoperability
requestData.setAllowNamespaceQualifiedPasswordTypes(true);

View File

@@ -0,0 +1,5 @@
package org.springframework.ws.soap.security.wss4j2;
public class AxiomWss4jMessageInterceptorSamlTest extends Wss4jMessageInterceptorSamlTestCase {
}

View File

@@ -0,0 +1,5 @@
package org.springframework.ws.soap.security.wss4j2;
public class SaajWss4jMessageInterceptorSamlTest extends Wss4jMessageInterceptorSamlTestCase {
}

View File

@@ -0,0 +1,111 @@
package org.springframework.ws.soap.security.wss4j2;
import java.io.IOException;
import java.security.cert.X509Certificate;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoType;
import org.apache.wss4j.common.crypto.Merlin;
import org.apache.wss4j.common.saml.SAMLCallback;
import org.apache.wss4j.common.saml.bean.KeyInfoBean;
import org.apache.wss4j.common.saml.bean.SubjectBean;
import org.apache.wss4j.common.saml.bean.Version;
import org.apache.wss4j.common.saml.builder.SAML2Constants;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.security.wss4j2.support.CryptoFactoryBean;
import org.w3c.dom.Document;
public abstract class Wss4jMessageInterceptorSamlTestCase extends Wss4jTestCase {
protected Wss4jSecurityInterceptor interceptor;
@Override
protected void onSetup() throws Exception {
interceptor = new Wss4jSecurityInterceptor();
interceptor.setSecurementActions("SAMLTokenSigned");
interceptor.setValidationActions("SAMLTokenSigned Signature");
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setCryptoProvider(Merlin.class);
cryptoFactoryBean.setKeyStoreType("jceks");
cryptoFactoryBean.setKeyStorePassword("123456");
cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("private.jks"));
cryptoFactoryBean.afterPropertiesSet();
Crypto crypto = cryptoFactoryBean.getObject();
CryptoType type = new CryptoType(CryptoType.TYPE.ALIAS);
type.setAlias("rsaKey");
X509Certificate userCertificate = crypto.getX509Certificates(type)[0];
interceptor.setSecurementSignatureCrypto(crypto);
interceptor.setValidationSignatureCrypto(crypto);
interceptor.setSecurementSamlCallbackHandler(getSamlCalbackHandler(crypto, userCertificate));
interceptor.afterPropertiesSet();
}
@Test
public void testAddSAML() throws Exception
{
interceptor.setSecurementPassword("123456");
interceptor.setSecurementUsername("rsaKey");
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext messageContext = getSoap11MessageContext(message);
interceptor.secureMessage(message, messageContext);
Document document = getDocument(message);
assertXpathExists("Absent SAML Assertion element",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/saml:Assertion", document);
// lets verify the signature that we've just generated
interceptor.validateMessage(message, messageContext);
}
protected CallbackHandler getSamlCalbackHandler(Crypto crypto, X509Certificate userCert)
{
return new SamlCallbackHandler(crypto, userCert);
}
private class SamlCallbackHandler implements CallbackHandler {
private Crypto crypto;
private X509Certificate userCertificate;
public SamlCallbackHandler(Crypto crypto, X509Certificate userCertificate)
{
this.crypto = crypto;
this.userCertificate = userCertificate;
}
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof SAMLCallback) {
SAMLCallback callback = (SAMLCallback) callbacks[i];
callback.setSamlVersion(Version.SAML_20);
callback.setIssuerCrypto(crypto);
callback.setIssuerKeyName("rsaKey");
callback.setIssuerKeyPassword("123456");
callback.setIssuer("test-issuer");
SubjectBean subject = new SubjectBean("test-subject", "", SAML2Constants.CONF_BEARER);
KeyInfoBean keyInfo = new KeyInfoBean();
keyInfo.setCertificate(userCertificate);
subject.setKeyInfo(keyInfo);
callback.setSubject(subject);
callback.setSignAssertion(true);
}
}
}
}
}

View File

@@ -79,6 +79,7 @@ public abstract class Wss4jTestCase {
namespaces.put("echo", "http://www.springframework.org/spring-ws/samples/echo");
namespaces.put("wsu",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
namespaces.put("saml", "urn:oasis:names:tc:SAML:2.0:assertion");
namespaces.put("test", "http://test");
xpathTemplate.setNamespaces(namespaces);
onSetup();