Author: coheigea
Date: Wed Jun 1 15:47:33 2011
New Revision: 1130195
URL: http://svn.apache.org/viewvc?rev=1130195&view=rev
Log:
[CXF-3565] - Support pluggable way of configuring WS-Trust ActAs and OnBehalfOf
behaviour
Added:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/DelegationCallback.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/ReceivedTokenCallbackHandler.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/WSSUsernameCallbackHandler.java
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java?rev=1130195&r1=1130194&r2=1130195&view=diff
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
(original)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
Wed Jun 1 15:47:33 2011
@@ -105,6 +105,8 @@ public final class SecurityConstants {
public static final String STS_TOKEN_DO_CANCEL =
"ws-security.sts.token.do.cancel";
public static final String STS_TOKEN_ACT_AS =
"ws-security.sts.token.act-as";
+
+ public static final String STS_TOKEN_ON_BEHALF_OF =
"ws-security.sts.token.on-behalf-of";
public static final Set<String> ALL_PROPERTIES;
@@ -118,7 +120,7 @@ public final class SecurityConstants {
STS_TOKEN_ACT_AS, STS_TOKEN_USERNAME,
STS_TOKEN_USE_CERT_FOR_KEYINFO,
SAML1_TOKEN_VALIDATOR, SAML2_TOKEN_VALIDATOR,
TIMESTAMP_TOKEN_VALIDATOR,
SIGNATURE_TOKEN_VALIDATOR, IS_BSP_COMPLIANT, TIMESTAMP_FUTURE_TTL,
- BST_TOKEN_VALIDATOR, SAML_CALLBACK_HANDLER
+ BST_TOKEN_VALIDATOR, SAML_CALLBACK_HANDLER, STS_TOKEN_ON_BEHALF_OF
}));
ALL_PROPERTIES = Collections.unmodifiableSet(s);
}
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java?rev=1130195&r1=1130194&r2=1130195&view=diff
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java
(original)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java
Wed Jun 1 15:47:33 2011
@@ -123,10 +123,19 @@ public class IssuedTokenInterceptorProvi
}
synchronized (client) {
try {
- // Transpose ActAs info from original request
to the STS client.
- client.setActAs(
-
message.getContextualProperty(SecurityConstants.STS_TOKEN_ACT_AS));
+ // Transpose ActAs/OnBehalfOf info from
original request to the STS client.
+ Object token =
+
message.getContextualProperty(SecurityConstants.STS_TOKEN_ACT_AS);
+ if (token != null) {
+ client.setActAs(token);
+ }
+ token =
+
message.getContextualProperty(SecurityConstants.STS_TOKEN_ON_BEHALF_OF);
+ if (token != null) {
+ client.setOnBehalfOf(token);
+ }
+ client.setMessage(message);
client.setTrust(getTrust10(aim));
client.setTrust(getTrust13(aim));
client.setTemplate(itok.getRstTemplate());
@@ -188,6 +197,7 @@ public class IssuedTokenInterceptorProvi
}
return (Trust13)ais.iterator().next().getAssertion();
}
+
}
static class IssuedTokenInInterceptor extends
AbstractPhaseInterceptor<Message> {
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java?rev=1130195&r1=1130194&r2=1130195&view=diff
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
(original)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
Wed Jun 1 15:47:33 2011
@@ -35,6 +35,7 @@ import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
@@ -94,6 +95,7 @@ import org.apache.cxf.ws.security.policy
import org.apache.cxf.ws.security.policy.model.Trust10;
import org.apache.cxf.ws.security.policy.model.Trust13;
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
+import org.apache.cxf.ws.security.trust.delegation.DelegationCallback;
import org.apache.cxf.wsdl11.WSDLServiceFactory;
import org.apache.neethi.All;
import org.apache.neethi.ExactlyOne;
@@ -141,7 +143,7 @@ public class STSClient implements Config
AlgorithmSuite algorithmSuite;
String namespace = STSUtils.WST_NS_05_12;
String addressingNamespace;
- Element onBehalfOfElement;
+ Object onBehalfOf;
boolean useCertificateForConfirmationKeyInfo;
boolean isSecureConv;
@@ -151,6 +153,7 @@ public class STSClient implements Config
String tokenType;
String keyType;
boolean sendKeyType = true;
+ Message message;
Map<String, Object> ctx = new HashMap<String, Object>();
@@ -179,6 +182,10 @@ public class STSClient implements Config
public void setLocation(String location) {
this.location = location;
}
+
+ public void setMessage(Message message) {
+ this.message = message;
+ }
/**
* Sets the WS-P policy that is applied to communications between this
client and the remote server
@@ -320,10 +327,15 @@ public class STSClient implements Config
this.keyType = keyType;
}
+ @Deprecated
public void setOnBehalfOfElement(Element onBehalfOfElement) {
- this.onBehalfOfElement = onBehalfOfElement;
+ this.onBehalfOf = onBehalfOfElement;
}
+ public void setOnBehalfOf(Object onBehalfOf) {
+ this.onBehalfOf = onBehalfOf;
+ }
+
/**
* Indicate whether to use the signer's public X509 certificate for the
subject confirmation key info
* when creating a RequestsSecurityToken message. If the property is set
to 'false', only the public key
@@ -609,11 +621,32 @@ public class STSClient implements Config
writer.writeEndElement();
}
- private void addOnBehalfOf(W3CDOMStreamWriter writer) throws
XMLStreamException {
- if (onBehalfOfElement != null) {
- writer.writeStartElement("wst", "OnBehalfOf", namespace);
- StaxUtils.copy(onBehalfOfElement, writer);
- writer.writeEndElement();
+ private void addOnBehalfOf(W3CDOMStreamWriter writer) throws Exception {
+ if (this.onBehalfOf != null) {
+ final boolean isString = this.onBehalfOf instanceof String;
+ final boolean isElement = this.onBehalfOf instanceof Element;
+ final boolean isCallbackHandler = this.onBehalfOf instanceof
CallbackHandler;
+ if (isString || isElement || isCallbackHandler) {
+ final Element tokenElement;
+
+ if (isString) {
+ final Document acAsDoc =
+ DOMUtils.readXml(new StringReader((String)
this.onBehalfOf));
+ tokenElement = acAsDoc.getDocumentElement();
+ } else if (isElement) {
+ tokenElement = (Element)this.onBehalfOf;
+ } else {
+ DelegationCallback callback = new
DelegationCallback(message);
+ ((CallbackHandler)onBehalfOf).handle(new
Callback[]{callback});
+ tokenElement = callback.getToken();
+ }
+
+ if (tokenElement != null) {
+ writer.writeStartElement("wst", "OnBehalfOf", namespace);
+ StaxUtils.copy(tokenElement, writer);
+ writer.writeEndElement();
+ }
+ }
}
}
@@ -914,27 +947,27 @@ public class STSClient implements Config
if (this.actAs != null) {
final boolean isString = this.actAs instanceof String;
final boolean isElement = this.actAs instanceof Element;
- if (isString || isElement) {
- final Element actAsEl;
+ final boolean isCallbackHandler = this.actAs instanceof
CallbackHandler;
+ if (isString || isElement || isCallbackHandler) {
+ final Element tokenElement;
if (isString) {
final Document acAsDoc =
DOMUtils.readXml(new StringReader((String)
this.actAs));
- actAsEl = acAsDoc.getDocumentElement();
+ tokenElement = acAsDoc.getDocumentElement();
+ } else if (isElement) {
+ tokenElement = (Element) this.actAs;
} else {
- actAsEl = (Element) this.actAs;
+ DelegationCallback callback = new
DelegationCallback(message);
+ ((CallbackHandler)actAs).handle(new Callback[]{callback});
+ tokenElement = callback.getToken();
}
- writer.writeStartElement(STSUtils.WST_NS_08_02, "ActAs");
-
- // Unlikely to ever be otherwise, but still prudent to check.
- if (actAsEl.getOwnerDocument() != writer.getDocument()) {
- writer.getDocument().adoptNode(actAsEl);
+ if (tokenElement != null) {
+ writer.writeStartElement(STSUtils.WST_NS_08_02, "ActAs");
+ StaxUtils.copy(tokenElement, writer);
+ writer.writeEndElement();
}
-
- writer.getCurrentNode().appendChild(actAsEl);
-
- writer.writeEndElement();
}
}
}
Added:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/DelegationCallback.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/DelegationCallback.java?rev=1130195&view=auto
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/DelegationCallback.java
(added)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/DelegationCallback.java
Wed Jun 1 15:47:33 2011
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.ws.security.trust.delegation;
+
+import javax.security.auth.callback.Callback;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.message.Message;
+
+/**
+ * This Callback class provides a pluggable way of performing delegation. A
CallbackHandler
+ * instance will be supplied with this class, which contains a reference to
the current
+ * Message. The CallbackHandler implementation is required to set the token
Element to be
+ * sent in the request.
+ */
+public class DelegationCallback implements Callback {
+
+ private Element token;
+
+ private Message currentMessage;
+
+ public DelegationCallback() {
+ //
+ }
+
+ public DelegationCallback(Message currentMessage) {
+ this.currentMessage = currentMessage;
+ }
+
+ public void setToken(Element token) {
+ this.token = token;
+ }
+
+ public Element getToken() {
+ return token;
+ }
+
+ public void setCurrentMessage(Message currentMessage) {
+ this.currentMessage = currentMessage;
+ }
+
+ public Message getCurrentMessage() {
+ return currentMessage;
+ }
+
+}
Added:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/ReceivedTokenCallbackHandler.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/ReceivedTokenCallbackHandler.java?rev=1130195&view=auto
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/ReceivedTokenCallbackHandler.java
(added)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/ReceivedTokenCallbackHandler.java
Wed Jun 1 15:47:33 2011
@@ -0,0 +1,113 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.ws.security.trust.delegation;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.List;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.handler.WSHandlerResult;
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+
+/**
+ * This CallbackHandler implementation obtains the previously received message
from a
+ * DelegationCallback object, and obtains a received token
+ * (SAML/UsernameToken/BinarySecurityToken) from it to be used as the
delegation token.
+ */
+public class ReceivedTokenCallbackHandler implements CallbackHandler {
+
+ @SuppressWarnings("unchecked")
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof DelegationCallback) {
+ DelegationCallback callback = (DelegationCallback)
callbacks[i];
+ Message message = callback.getCurrentMessage();
+
+ if (message != null
+ && message.get(PhaseInterceptorChain.PREVIOUS_MESSAGE) !=
null) {
+ WeakReference<SoapMessage> wr =
+ (WeakReference<SoapMessage>)
+
message.get(PhaseInterceptorChain.PREVIOUS_MESSAGE);
+ SoapMessage previousSoapMessage = wr.get();
+ Element token = getTokenFromMessage(previousSoapMessage);
+ callback.setToken(token);
+ }
+
+ } else {
+ throw new UnsupportedCallbackException(callbacks[i],
"Unrecognized Callback");
+ }
+ }
+ }
+
+ private Element getTokenFromMessage(SoapMessage soapMessage) {
+ List<WSHandlerResult> results =
+
CastUtils.cast((List<?>)soapMessage.get(WSHandlerConstants.RECV_RESULTS));
+ if (results != null) {
+ for (WSHandlerResult rResult : results) {
+ Element token = findToken(rResult.getResults());
+ if (token != null) {
+ return token;
+ }
+ }
+ }
+ return null;
+ }
+
+ private Element findToken(
+ List<WSSecurityEngineResult> wsSecEngineResults
+ ) {
+ for (WSSecurityEngineResult wser : wsSecEngineResults) {
+ Integer actInt =
(Integer)wser.get(WSSecurityEngineResult.TAG_ACTION);
+ if (actInt.intValue() == WSConstants.ST_SIGNED
+ || actInt.intValue() == WSConstants.ST_UNSIGNED) {
+ AssertionWrapper assertion =
+
(AssertionWrapper)wser.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
+ return assertion.getElement();
+ } else if (actInt.intValue() == WSConstants.UT
+ || actInt.intValue() == WSConstants.UT_NOPASSWORD) {
+ UsernameToken token =
+
(UsernameToken)wser.get(WSSecurityEngineResult.TAG_USERNAME_TOKEN);
+ return token.getElement();
+ } else if (actInt.intValue() == WSConstants.BST) {
+ BinarySecurity token =
+
(BinarySecurity)wser.get(WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN);
+ return token.getElement();
+ }
+ }
+ return null;
+ }
+
+}
Added:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/WSSUsernameCallbackHandler.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/WSSUsernameCallbackHandler.java?rev=1130195&view=auto
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/WSSUsernameCallbackHandler.java
(added)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/WSSUsernameCallbackHandler.java
Wed Jun 1 15:47:33 2011
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.ws.security.trust.delegation;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.ws.security.SecurityConstants;
+import org.apache.ws.security.message.WSSecUsernameToken;
+
+/**
+ * This CallbackHandler implementation obtains a username via the jaxws
property
+ * "ws-security.username", as defined in SecurityConstants, and creates a wss
UsernameToken
+ * (with no password) to be used as the delegation token.
+ */
+public class WSSUsernameCallbackHandler implements CallbackHandler {
+
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof DelegationCallback) {
+ DelegationCallback callback = (DelegationCallback)
callbacks[i];
+ Message message = callback.getCurrentMessage();
+
+ String username =
+
(String)message.getContextualProperty(SecurityConstants.USERNAME);
+ if (username != null) {
+ Node contentNode = message.getContent(Node.class);
+ Document doc = null;
+ if (contentNode != null) {
+ doc = contentNode.getOwnerDocument();
+ } else {
+ doc = DOMUtils.createDocument();
+ }
+ Element token = createWSSEUsernameToken(username, doc);
+ callback.setToken(token);
+ }
+ } else {
+ throw new UnsupportedCallbackException(callbacks[i],
"Unrecognized Callback");
+ }
+ }
+ }
+
+ private Element createWSSEUsernameToken(String username, Document doc) {
+ WSSecUsernameToken builder = new WSSecUsernameToken();
+ builder.setPasswordType(null);
+ builder.setUserInfo(username, null);
+ builder.prepare(doc);
+ return builder.getUsernameTokenElement();
+ }
+
+}