Author: coheigea
Date: Wed Sep 21 14:16:40 2011
New Revision: 1173661
URL: http://svn.apache.org/viewvc?rev=1173661&view=rev
Log:
Defer token validation to the WSS4J Validator interface + make it pluggable
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/X509TokenValidator.java
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/X509TokenValidatorTest.java
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java?rev=1173661&r1=1173660&r2=1173661&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
Wed Sep 21 14:16:40 2011
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.cxf.sts.token.validator;
import java.util.logging.Level;
@@ -42,6 +41,7 @@ import org.apache.ws.security.saml.SAMLK
import org.apache.ws.security.saml.ext.AssertionWrapper;
import org.apache.ws.security.validate.Credential;
import org.apache.ws.security.validate.SignatureTrustValidator;
+import org.apache.ws.security.validate.Validator;
/**
* Validate a SAML Assertion. It is valid if it was issued and signed by this
STS.
@@ -50,6 +50,16 @@ public class SAMLTokenValidator implemen
private static final Logger LOG =
LogUtils.getL7dLogger(SAMLTokenValidator.class);
+ private Validator validator = new SignatureTrustValidator();
+
+ /**
+ * Set the WSS4J Validator instance to use to validate the token.
+ * @param validator the WSS4J Validator instance to use to validate the
token
+ */
+ public void setValidator(Validator validator) {
+ this.validator = validator;
+ }
+
/**
* Return true if this TokenValidator implementation is capable of
validating the
* ReceivedToken argument.
@@ -89,39 +99,40 @@ public class SAMLTokenValidator implemen
TokenValidatorResponse response = new TokenValidatorResponse();
response.setValid(false);
- if (validateTarget != null && validateTarget.isDOMElement()) {
- try {
- Element validateTargetElement =
(Element)validateTarget.getToken();
- AssertionWrapper assertion = new
AssertionWrapper(validateTargetElement);
- if (!assertion.isSigned()) {
- LOG.log(Level.WARNING, "The received assertion is not
signed, and therefore not trusted");
- return response;
- }
- // Verify the signature
- assertion.verifySignature(
- requestData, new
WSDocInfo(validateTargetElement.getOwnerDocument())
- );
-
- // Now verify trust on the signature
- Credential trustCredential = new Credential();
- SAMLKeyInfo samlKeyInfo = assertion.getSignatureKeyInfo();
- trustCredential.setPublicKey(samlKeyInfo.getPublicKey());
- trustCredential.setCertificates(samlKeyInfo.getCerts());
-
- SignatureTrustValidator trustValidator = new
SignatureTrustValidator();
- trustValidator.validate(trustCredential, requestData);
-
- // Finally check the issuer
- String assertionIssuer = assertion.getIssuerString();
-
- if (issuer.equals(assertionIssuer)) {
- response.setValid(true);
- SAMLTokenPrincipal samlPrincipal = new
SAMLTokenPrincipal(assertion);
- response.setPrincipal(samlPrincipal);
- }
- } catch (WSSecurityException ex) {
- LOG.log(Level.WARNING, "", ex);
+ if (validateTarget == null || !validateTarget.isDOMElement()) {
+ return response;
+ }
+
+ try {
+ Element validateTargetElement = (Element)validateTarget.getToken();
+ AssertionWrapper assertion = new
AssertionWrapper(validateTargetElement);
+ if (!assertion.isSigned()) {
+ LOG.log(Level.WARNING, "The received assertion is not signed,
and therefore not trusted");
+ return response;
+ }
+ // Verify the signature
+ assertion.verifySignature(
+ requestData, new
WSDocInfo(validateTargetElement.getOwnerDocument())
+ );
+
+ // Now verify trust on the signature
+ Credential trustCredential = new Credential();
+ SAMLKeyInfo samlKeyInfo = assertion.getSignatureKeyInfo();
+ trustCredential.setPublicKey(samlKeyInfo.getPublicKey());
+ trustCredential.setCertificates(samlKeyInfo.getCerts());
+
+ validator.validate(trustCredential, requestData);
+
+ // Finally check the issuer
+ String assertionIssuer = assertion.getIssuerString();
+
+ if (issuer.equals(assertionIssuer)) {
+ response.setValid(true);
+ SAMLTokenPrincipal samlPrincipal = new
SAMLTokenPrincipal(assertion);
+ response.setPrincipal(samlPrincipal);
}
+ } catch (WSSecurityException ex) {
+ LOG.log(Level.WARNING, "", ex);
}
return response;
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java?rev=1173661&r1=1173660&r2=1173661&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
Wed Sep 21 14:16:40 2011
@@ -16,40 +16,39 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.cxf.sts.token.validator;
-import java.io.IOException;
import java.security.Principal;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.sts.QNameConstants;
import org.apache.cxf.sts.STSPropertiesMBean;
import org.apache.cxf.sts.request.ReceivedToken;
import org.apache.cxf.sts.request.TokenRequirements;
-import org.apache.cxf.ws.security.sts.provider.model.secext.EncodedString;
-import org.apache.cxf.ws.security.sts.provider.model.secext.PasswordString;
import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
import org.apache.ws.security.WSConstants;
-import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.handler.RequestData;
-import org.apache.ws.security.message.token.BinarySecurity;
import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.validate.Credential;
+import org.apache.ws.security.validate.Validator;
/**
* This class validates a wsse UsernameToken.
@@ -58,6 +57,16 @@ public class UsernameTokenValidator impl
private static final Logger LOG =
LogUtils.getL7dLogger(UsernameTokenValidator.class);
+ private Validator validator = new
org.apache.ws.security.validate.UsernameTokenValidator();
+
+ /**
+ * Set the WSS4J Validator instance to use to validate the token.
+ * @param validator the WSS4J Validator instance to use to validate the
token
+ */
+ public void setValidator(Validator validator) {
+ this.validator = validator;
+ }
+
/**
* Return true if this TokenValidator implementation is capable of
validating the
* ReceivedToken argument.
@@ -89,109 +98,60 @@ public class UsernameTokenValidator impl
TokenValidatorResponse response = new TokenValidatorResponse();
response.setValid(false);
- if (validateTarget != null && validateTarget.isUsernameToken()) {
- //
- // Parse the JAXB object
- //
- String passwordType = null;
- String passwordValue = null;
- String nonce = null;
- String created = null;
- UsernameTokenType usernameTokenType =
(UsernameTokenType)validateTarget.getToken();
- for (Object any : usernameTokenType.getAny()) {
- if (any instanceof JAXBElement<?>) {
- JAXBElement<?> anyElement = (JAXBElement<?>) any;
- if (QNameConstants.PASSWORD.equals(anyElement.getName())) {
- PasswordString passwordString =
- (PasswordString)anyElement.getValue();
- passwordType = passwordString.getType();
- passwordValue = passwordString.getValue();
- } else if
(QNameConstants.NONCE.equals(anyElement.getName())) {
- EncodedString nonceES =
(EncodedString)anyElement.getValue();
- nonce = nonceES.getValue();
- // Encoding Type must be equal to Base64Binary
- if
(!BinarySecurity.BASE64_ENCODING.equals(nonceES.getEncodingType())) {
- String errorMsg = "The UsernameToken nonce element
has a bad encoding type";
- LOG.log(Level.WARNING, errorMsg + " : " +
nonceES.getEncodingType());
- return response;
- }
- }
- } else if (any instanceof Element) {
- Element element = (Element)any;
- if (WSConstants.WSU_NS.equals(element.getNamespaceURI())
- &&
WSConstants.CREATED_LN.equals(element.getLocalName())) {
- created = element.getTextContent();
- }
- }
- }
-
- //
- // Validate the token
- //
- try {
- boolean valid =
- verifyPassword(
- usernameTokenType.getUsername().getValue(),
passwordValue, passwordType,
- nonce, created, requestData
- );
- response.setValid(valid);
- if (valid) {
- Principal principal =
- createPrincipal(
- usernameTokenType.getUsername().getValue(),
passwordValue, passwordType,
- nonce, created
- );
- response.setPrincipal(principal);
- }
- } catch (WSSecurityException ex) {
- LOG.log(Level.WARNING, "", ex);
- }
+ if (validateTarget == null || !validateTarget.isUsernameToken()) {
+ return response;
}
-
- return response;
- }
-
- private boolean verifyPassword(
- String username,
- String passwordValue,
- String passwordType,
- String nonce,
- String createdTime,
- RequestData requestData
- ) throws WSSecurityException {
- WSPasswordCallback pwCb =
- new WSPasswordCallback(
- username, null, passwordType,
WSPasswordCallback.USERNAME_TOKEN, requestData
- );
+
+ //
+ // Turn the JAXB UsernameTokenType into a DOM Element for validation
+ //
+ UsernameTokenType usernameTokenType =
(UsernameTokenType)validateTarget.getToken();
+ Element rootElement = null;
try {
- requestData.getCallbackHandler().handle(new Callback[]{pwCb});
- } catch (IOException e) {
- LOG.log(Level.WARNING, "", e);
- throw new WSSecurityException(
- WSSecurityException.FAILED_AUTHENTICATION, null, null, e
- );
- } catch (UnsupportedCallbackException e) {
- LOG.log(Level.WARNING, "", e);
- throw new WSSecurityException(
- WSSecurityException.FAILED_AUTHENTICATION, null, null, e
- );
+ JAXBContext jaxbContext =
+
JAXBContext.newInstance("org.apache.cxf.ws.security.sts.provider.model");
+ Marshaller marshaller = jaxbContext.createMarshaller();
+ Document doc = DOMUtils.createDocument();
+ rootElement = doc.createElement("root-element");
+ JAXBElement<UsernameTokenType> tokenType =
+ new JAXBElement<UsernameTokenType>(
+ QNameConstants.USERNAME_TOKEN, UsernameTokenType.class,
usernameTokenType
+ );
+ marshaller.marshal(tokenType, rootElement);
+ } catch (JAXBException ex) {
+ LOG.log(Level.WARNING, "", ex);
+ return response;
}
- String origPassword = pwCb.getPassword();
- if (origPassword == null) {
- LOG.fine("Callback supplied no password for: " + username);
- return false;
- }
- if (WSConstants.PASSWORD_DIGEST.equals(passwordType)) {
- String passDigest = UsernameToken.doPasswordDigest(nonce,
createdTime, origPassword);
- if (!passDigest.equals(passwordValue)) {
- return false;
- }
- } else {
- if (!origPassword.equals(passwordValue)) {
- return false;
+
+ //
+ // Validate the token
+ //
+ try {
+ boolean allowNamespaceQualifiedPasswordTypes =
+ wssConfig.getAllowNamespaceQualifiedPasswordTypes();
+ boolean bspCompliant = wssConfig.isWsiBSPCompliant();
+ Element usernameTokenElement =
(Element)rootElement.getFirstChild();
+
+ UsernameToken ut =
+ new UsernameToken(usernameTokenElement,
allowNamespaceQualifiedPasswordTypes, bspCompliant);
+ if (ut.getPassword() == null) {
+ return response;
}
+ Credential credential = new Credential();
+ credential.setUsernametoken(ut);
+ validator.validate(credential, requestData);
+
+ Principal principal =
+ createPrincipal(
+ ut.getName(), ut.getPassword(), ut.getPasswordType(),
ut.getNonce(), ut.getCreated()
+ );
+ response.setPrincipal(principal);
+ response.setValid(true);
+ } catch (WSSecurityException ex) {
+ LOG.log(Level.WARNING, "", ex);
}
- return true;
+
+ return response;
}
/**
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/X509TokenValidator.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/X509TokenValidator.java?rev=1173661&r1=1173660&r2=1173661&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/X509TokenValidator.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/X509TokenValidator.java
Wed Sep 21 14:16:40 2011
@@ -36,16 +36,12 @@ import org.apache.cxf.sts.request.TokenR
import
org.apache.cxf.ws.security.sts.provider.model.secext.BinarySecurityTokenType;
import org.apache.ws.security.WSConstants;
-import org.apache.ws.security.WSDocInfo;
import org.apache.ws.security.WSSConfig;
-import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.handler.RequestData;
import org.apache.ws.security.message.token.BinarySecurity;
import org.apache.ws.security.message.token.X509Security;
-import org.apache.ws.security.processor.BinarySecurityTokenProcessor;
-import org.apache.ws.security.processor.Processor;
import org.apache.ws.security.validate.Credential;
import org.apache.ws.security.validate.SignatureTrustValidator;
import org.apache.ws.security.validate.Validator;
@@ -58,9 +54,21 @@ public class X509TokenValidator implemen
public static final String X509_V3_TYPE = WSConstants.X509TOKEN_NS +
"#X509v3";
+ public static final String BASE64_ENCODING = WSConstants.SOAPMESSAGE_NS +
"#Base64Binary";
+
private static final Logger LOG =
LogUtils.getL7dLogger(X509TokenValidator.class);
+
+ private Validator validator = new SignatureTrustValidator();
/**
+ * Set the WSS4J Validator instance to use to validate the token.
+ * @param validator the WSS4J Validator instance to use to validate the
token
+ */
+ public void setValidator(Validator validator) {
+ this.validator = validator;
+ }
+
+ /**
* Return true if this TokenValidator implementation is capable of
validating the
* ReceivedToken argument.
*/
@@ -87,55 +95,53 @@ public class X509TokenValidator implemen
RequestData requestData = new RequestData();
requestData.setSigCrypto(sigCrypto);
- WSSConfig wssConfig = WSSConfig.getNewInstance();
- wssConfig.setValidator(WSSecurityEngine.BINARY_TOKEN,
BSTValidator.class);
- requestData.setWssConfig(wssConfig);
+ requestData.setWssConfig(WSSConfig.getNewInstance());
requestData.setCallbackHandler(callbackHandler);
TokenValidatorResponse response = new TokenValidatorResponse();
response.setValid(false);
- if (validateTarget != null && validateTarget.isBinarySecurityToken()) {
- BinarySecurityTokenType binarySecurityType =
- (BinarySecurityTokenType)validateTarget.getToken();
- //
- // Turn the received JAXB object into a DOM element
- //
- Document doc = DOMUtils.createDocument();
- BinarySecurity binarySecurity = new X509Security(doc);
-
binarySecurity.setEncodingType(binarySecurityType.getEncodingType());
- String data = binarySecurityType.getValue();
- ((Text)binarySecurity.getElement().getFirstChild()).setData(data);
-
- //
- // Process and Validate the token
- //
- Processor processor = new BinarySecurityTokenProcessor();
- try {
- processor.handleToken(
- binarySecurity.getElement(), requestData, new
WSDocInfo(doc)
- );
- X509Certificate cert = ((X509Security)
binarySecurity).getX509Certificate(sigCrypto);
- response.setPrincipal(cert.getSubjectX500Principal());
- response.setValid(true);
- } catch (WSSecurityException ex) {
- LOG.log(Level.WARNING, "", ex);
- }
+ if (validateTarget == null || !validateTarget.isBinarySecurityToken())
{
+ return response;
}
- return response;
- }
-
- /**
- * A Custom Validator for a BinarySecurityToken - it just sends the
BinarySecurityToken
- * to the SignatureTrustValidator for validation.
- */
- public static class BSTValidator implements Validator {
- public Credential validate(Credential credential, RequestData data)
throws WSSecurityException {
- Validator delegate = new SignatureTrustValidator();
- return delegate.validate(credential, data);
+ BinarySecurityTokenType binarySecurityType =
(BinarySecurityTokenType)validateTarget.getToken();
+
+ // Test the encoding type
+ String encodingType = binarySecurityType.getEncodingType();
+ if (!BASE64_ENCODING.equals(encodingType)) {
+ LOG.fine("Bad encoding type attribute specified: " + encodingType);
+ return response;
}
-
+
+ //
+ // Turn the received JAXB object into a DOM element
+ //
+ Document doc = DOMUtils.createDocument();
+ BinarySecurity binarySecurity = new X509Security(doc);
+ binarySecurity.setEncodingType(encodingType);
+ binarySecurity.setValueType(binarySecurityType.getValueType());
+ String data = binarySecurityType.getValue();
+ ((Text)binarySecurity.getElement().getFirstChild()).setData(data);
+
+ //
+ // Validate the token
+ //
+ try {
+ Credential credential = new Credential();
+ credential.setBinarySecurityToken(binarySecurity);
+ if (sigCrypto != null) {
+ X509Certificate cert =
((X509Security)binarySecurity).getX509Certificate(sigCrypto);
+ credential.setCertificates(new X509Certificate[]{cert});
+ }
+
+ Credential returnedCredential = validator.validate(credential,
requestData);
+
response.setPrincipal(returnedCredential.getCertificates()[0].getSubjectX500Principal());
+ response.setValid(true);
+ } catch (WSSecurityException ex) {
+ LOG.log(Level.WARNING, "", ex);
+ }
+ return response;
}
}
Modified:
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/X509TokenValidatorTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/X509TokenValidatorTest.java?rev=1173661&r1=1173660&r2=1173661&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/X509TokenValidatorTest.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/X509TokenValidatorTest.java
Wed Sep 21 14:16:40 2011
@@ -82,13 +82,9 @@ public class X509TokenValidatorTest exte
// This will fail as the encoding type is not set
TokenValidatorResponse validatorResponse = null;
- try {
- validatorResponse =
x509TokenValidator.validateToken(validatorParameters);
- assertTrue(validatorResponse != null);
- assertFalse(validatorResponse.isValid());
- } catch (RuntimeException ex) {
- // needed due to a bug in WSS4J 1.6.2
- }
+ validatorResponse =
x509TokenValidator.validateToken(validatorParameters);
+ assertTrue(validatorResponse != null);
+ assertFalse(validatorResponse.isValid());
binarySecurityToken.setEncodingType(WSConstants.SOAPMESSAGE_NS +
"#Base64Binary");