Author: pskopek(a)redhat.com
Date: 2012-07-04 10:43:50 -0400 (Wed, 04 Jul 2012)
New Revision: 1563
Added:
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/BinaryTokenValidation.java
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/MapBasedTokenHandler.java
Modified:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/core/ErrorCodes.java
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/core/util/SOAPUtil.java
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/BinaryTokenHandler.java
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/jaas/JBWSTokenIssuingLoginModule.java
Log:
backport of [PRODMGT-153] Adding ability to use customer's own login module and
supply binary security token in JAAS sharedState Map and use in new MapBasedTokenHandler
to send it to STS.
Modified:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/core/ErrorCodes.java
===================================================================
---
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/core/ErrorCodes.java 2012-06-12
14:15:37 UTC (rev 1562)
+++
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/core/ErrorCodes.java 2012-07-04
14:43:50 UTC (rev 1563)
@@ -191,4 +191,6 @@
String WRITER_UNSUPPORTED_ATTRIB_VALUE = "PL00084: Writer: Unsupported Attribute
Value:";
String WRONG_TYPE = "PL00095: Wrong type:";
+
+ String SOAP_MESSAGE_DUMP_ERROR = "PL00104: Error while dumping SOAP
message:";
}
\ No newline at end of file
Modified:
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/core/util/SOAPUtil.java
===================================================================
---
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/core/util/SOAPUtil.java 2012-06-12
14:15:37 UTC (rev 1562)
+++
product/trunk/picketlink-core/src/main/java/org/picketlink/identity/federation/core/util/SOAPUtil.java 2012-07-04
14:43:50 UTC (rev 1563)
@@ -21,6 +21,7 @@
*/
package org.picketlink.identity.federation.core.util;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
@@ -33,6 +34,7 @@
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Source;
+import org.picketlink.identity.federation.core.ErrorCodes;
import org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil;
import org.w3c.dom.Document;
@@ -116,4 +118,20 @@
throw new RuntimeException(e);
}
}
+
+ /**
+ * Utility method to dump soapMessage to String.
+ * Used for logging purpose. Use only with TRACE level, please.
+ * @param soapMessage
+ * @return String representation of soapMessage
+ */
+ public static String soapMessageAsString(SOAPMessage soapMessage) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ soapMessage.writeTo(baos);
+ } catch (Exception almostIgnored) {
+ return ErrorCodes.SOAP_MESSAGE_DUMP_ERROR + almostIgnored;
+ }
+ return baos.toString();
+ }
}
\ No newline at end of file
Modified:
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/BinaryTokenHandler.java
===================================================================
---
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/BinaryTokenHandler.java 2012-06-12
14:15:37 UTC (rev 1562)
+++
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/BinaryTokenHandler.java 2012-07-04
14:43:50 UTC (rev 1563)
@@ -39,6 +39,7 @@
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.picketlink.identity.federation.core.ErrorCodes;
+import org.picketlink.identity.federation.core.util.SOAPUtil;
import org.picketlink.identity.federation.core.util.StringUtil;
import org.picketlink.trust.jbossws.Constants;
import org.picketlink.trust.jbossws.Util;
@@ -93,7 +94,7 @@
* Attribute value for the EncodingType attribute
*/
private String encodingType =
SecurityActions.getSystemProperty("binary.http.encodingType",
- "http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-soap-message-security-1.0#Base64Binary");
+
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
/**
* Attribute value for the ValueType attribute
@@ -259,15 +260,7 @@
}
if( trace)
{
- log.trace("SOAP Message=");
- try
- {
- sm.writeTo(System.out);
- }
- catch (Exception ignore)
- {
- log.trace("Exception tracing out SOAP Message", ignore);
- }
+ log.trace("SOAP Message=" + SOAPUtil.soapMessageAsString(sm));
}
return true;
}
Added:
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/BinaryTokenValidation.java
===================================================================
---
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/BinaryTokenValidation.java
(rev 0)
+++
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/BinaryTokenValidation.java 2012-07-04
14:43:50 UTC (rev 1563)
@@ -0,0 +1,33 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.picketlink.trust.jbossws.handler;
+
+import javax.xml.ws.handler.MessageContext;
+
+/**
+ * Interface for token validation to be supplied to @MapBasedTokenHandler and
@BinaryTokenHandler.
+ * @author pskopek
+ *
+ */
+public interface BinaryTokenValidation {
+ public boolean validateBinaryToken(Object token, MessageContext msgContext);
+}
Added:
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/MapBasedTokenHandler.java
===================================================================
---
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/MapBasedTokenHandler.java
(rev 0)
+++
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/handler/MapBasedTokenHandler.java 2012-07-04
14:43:50 UTC (rev 1563)
@@ -0,0 +1,317 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.picketlink.trust.jbossws.handler;
+
+import java.util.Map;
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPElement;
+import javax.xml.soap.SOAPEnvelope;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPFactory;
+import javax.xml.soap.SOAPHeader;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+
+import org.jboss.logging.Logger;
+import org.picketlink.identity.federation.core.ErrorCodes;
+import org.picketlink.identity.federation.core.util.SOAPUtil;
+import org.picketlink.trust.jbossws.Constants;
+import org.picketlink.trust.jbossws.Util;
+
+/**
+ * <p>
+ * Handler that looks for a binary token data that exists in jaasOptionsMap supplied in
constructor.
+ * </p>
+ * <p>
+ * <b>Configuration:</b>
+ * <p>
+ * <i>System Properties:</i>
+ * <ul>
+ * <li>map.token.key: key which will be used to fetch binary token from the
jaasOptionsMap. Default value is ClientID</li>
+ * <li>map.token.validation.class.key: validation class for binary token inside
handleInbound method</li>
+ * <li>binary.http.encodingType: attribute value of the EncodingType
attribute</li>
+ * <li>binary.http.valueType: attribute value of the ValueType
attribute</li>
+ * <li>binary.http.valueType.namespace: namespace for the ValueType
attribute</li>
+ * <li>binary.http.valueType.prefix: namespace for the ValueType
attribute</li>
+ * </ul>
+ * <i>Setters:</i>
+ * <p>
+ * Please see the see also section.
+ * </p>
+ *
+ * @see #setEncodingType(String)
+ * @see #setValueType(String)
+ * @see #setValueTypeNamespace(String)
+ * @see #setValueTypePrefix(String) </p> </p>
+ * @author Anil.Saldhana(a)redhat.com
+ * @author pskopek(a)redhat.com
+ * @since Jun 11, 2012
+ */
+public class MapBasedTokenHandler extends AbstractPicketLinkTrustHandler {
+
+ public static final String SYS_PROP_TOKEN_KEY = "map.token.key";
+ public static final String DEFAULT_TOKEN_KEY = "ClientID";
+
+
+ /**
+ * The JAAS shared options map key name for binary token to be stored in.
+ */
+ public final String tokenOptionKey = SecurityActions.getSystemProperty(
+ SYS_PROP_TOKEN_KEY, "ClientID");
+
+ /**
+ * Key in the JAAS options map to find class name to validate token in
+ * inbound message handle method.
+ */
+ public final String validationTokenClassKey = SecurityActions
+ .getSystemProperty("map.token.validation.class.key",
+ "tokenValidationClass");
+
+ /**
+ * Attribute value for the EncodingType attribute
+ */
+ private String encodingType = SecurityActions
+ .getSystemProperty(
+ "binary.http.encodingType",
+
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
+
+ /**
+ * Attribute value for the ValueType attribute
+ */
+ private String valueType = SecurityActions.getSystemProperty(
+ "binary.http.valueType", null);
+
+ /**
+ * Namespace for the ValueType. Can be null. If null, then a separate
+ * namespace is not added.
+ */
+ private String valueTypeNamespace = SecurityActions.getSystemProperty(
+ "binary.http.valueType.namespace", null);
+
+ /**
+ * Prefix for the ValueType. Can be null.
+ */
+ private String valueTypePrefix = SecurityActions.getSystemProperty(
+ "binary.http.valueType.prefix", null);
+
+ private SOAPFactory factory = null;
+
+ /**
+ * Shared options from calling login module (@see
+ *
+ * @JBWSTokenIssuingLoginModule).
+ */
+ private Map<String, ?> jaasLoginModuleOptions = null;
+
+ public MapBasedTokenHandler(Map<String, ?> jaasOptionsMap) {
+ jaasLoginModuleOptions = jaasOptionsMap;
+ }
+
+ /**
+ * <p>
+ * Set the EncodingType value.
+ * </p>
+ * <p>
+ * Alternatively, set the system property "binary.http.encodingType"
+ * </p>
+ *
+ * @param binaryEncodingType
+ */
+ public void setEncodingType(String binaryEncodingType) {
+ this.encodingType = binaryEncodingType;
+ }
+
+ /**
+ * <p>
+ * Set the Value type
+ * </p>
+ * <p>
+ * Alternatively, set the system property "binary.http.valueType"
+ * </p>
+ *
+ * @param binaryValueType
+ */
+ public void setValueType(String binaryValueType) {
+ this.valueType = binaryValueType;
+ }
+
+ /**
+ * <p>
+ * Set the ValueType Namespace
+ * </p>
+ * <p>
+ * Alternatively, set the system property
"binary.http.valueType.namespace"
+ * </p>
+ *
+ * @param binaryValueNamespace
+ */
+ public void setValueTypeNamespace(String binaryValueNamespace) {
+ this.valueTypeNamespace = binaryValueNamespace;
+ }
+
+ /**
+ * <p>
+ * Set the Value Type Prefix
+ * </p>
+ * <p>
+ * Alternatively, set the system property "binary.http.valueType.prefix"
+ * </p>
+ *
+ * @param binaryValuePrefix
+ */
+ public void setValueTypePrefix(String binaryValuePrefix) {
+ this.valueTypePrefix = binaryValuePrefix;
+ }
+
+ @Override
+ protected boolean handleInbound(MessageContext msgContext) {
+ if (trace) {
+ log.trace("Handling Inbound Message");
+ }
+
+ String tokenValidation = (String) jaasLoginModuleOptions
+ .get(validationTokenClassKey);
+ if (tokenValidation == null) {
+ return true;
+ }
+
+ BinaryTokenValidation validation = null;
+ try {
+ ClassLoader cl = SecurityActions.getClassLoader(getClass());
+ validation = (BinaryTokenValidation) cl.loadClass(tokenValidation)
+ .newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(ErrorCodes.CLASS_NOT_LOADED
+ + "Class not loaded:" + tokenValidation, e);
+ }
+ String token = getToken(msgContext);
+ if (trace) {
+ log.trace("Validating token=" + token);
+ }
+
+ return validation.validateBinaryToken(token, msgContext);
+ }
+
+ @Override
+ protected boolean handleOutbound(MessageContext msgContext) {
+ if (trace) {
+ log.trace("Handling Outbound Message");
+ }
+
+ String token = (String) jaasLoginModuleOptions.get(tokenOptionKey);
+ if (token == null)
+ throw new RuntimeException(ErrorCodes.INJECTED_VALUE_MISSING
+ + tokenOptionKey
+ + " has to be set by calling LoginMoule in option map.");
+
+ SOAPElement security = null;
+ try {
+ security = create(token);
+ } catch (SOAPException e) {
+ log.error("Unable to create binary token", e);
+ }
+ if (security == null) {
+ log.warn("Was not able to create security token. Just sending message
without binary token");
+ return true;
+ }
+ SOAPMessage sm = ((SOAPMessageContext) msgContext).getMessage();
+ SOAPEnvelope envelope;
+ try {
+ envelope = sm.getSOAPPart().getEnvelope();
+ SOAPHeader header = (SOAPHeader) Util.findElement(envelope,
+ new QName(envelope.getNamespaceURI(), "Header"));
+ if (header == null) {
+ header = (SOAPHeader) envelope.getOwnerDocument()
+ .createElementNS(envelope.getNamespaceURI(),
+ envelope.getPrefix() + ":Header");
+ envelope.insertBefore(header, envelope.getFirstChild());
+ }
+ header.addChildElement(security);
+ } catch (SOAPException e) {
+ log.error("Unable to create binary token", e);
+ }
+ if (trace) {
+ log.trace("SOAP Message=" + SOAPUtil.soapMessageAsString(sm));
+ }
+ return true;
+ }
+
+ /**
+ * Given a binary token, create a {@link SOAPElement}
+ *
+ * @param token
+ * @return
+ * @throws SOAPException
+ */
+ private SOAPElement create(String token) throws SOAPException {
+ if (factory == null)
+ factory = SOAPFactory.newInstance();
+ SOAPElement security = factory.createElement(Constants.WSSE_LOCAL,
+ Constants.WSSE_PREFIX, Constants.WSSE_NS);
+
+ if (valueTypeNamespace != null) {
+ security.addNamespaceDeclaration(valueTypePrefix,
+ valueTypeNamespace);
+ }
+
+ SOAPElement binarySecurityToken = factory.createElement(
+ Constants.WSSE_BINARY_SECURITY_TOKEN, Constants.WSSE_PREFIX,
+ Constants.WSSE_NS);
+ binarySecurityToken.addTextNode(token);
+ if (valueType != null && !valueType.isEmpty()) {
+ binarySecurityToken.setAttribute(Constants.WSSE_VALUE_TYPE,
+ valueType);
+ }
+ if (encodingType != null) {
+ binarySecurityToken.setAttribute(Constants.WSSE_ENCODING_TYPE,
+ encodingType);
+ }
+
+ security.addChildElement(binarySecurityToken);
+ return security;
+ }
+
+ private String getToken(MessageContext msgContext) {
+
+ SOAPMessage sm = ((SOAPMessageContext) msgContext).getMessage();
+ SOAPEnvelope envelope;
+ try {
+ envelope = sm.getSOAPPart().getEnvelope();
+ SOAPHeader header = (SOAPHeader) Util.findElement(envelope,
+ new QName(envelope.getNamespaceURI(), "Header"));
+
+ if (header == null) {
+ header = (SOAPHeader) envelope.getOwnerDocument()
+ .createElementNS(envelope.getNamespaceURI(),
+ envelope.getPrefix() + ":Header");
+ }
+ return Util.findElementByWsuId(header, "BinarySecurityToken")
+ .getTextContent();
+
+ } catch (SOAPException e) {
+ log.error("Unable to create binary token", e);
+ return null;
+ }
+ }
+
+}
\ No newline at end of file
Modified:
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/jaas/JBWSTokenIssuingLoginModule.java
===================================================================
---
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/jaas/JBWSTokenIssuingLoginModule.java 2012-06-12
14:15:37 UTC (rev 1562)
+++
product/trunk/picketlink-core/src/main/java/org/picketlink/trust/jbossws/jaas/JBWSTokenIssuingLoginModule.java 2012-07-04
14:43:50 UTC (rev 1563)
@@ -22,6 +22,7 @@
package org.picketlink.trust.jbossws.jaas;
import java.security.Principal;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -44,6 +45,7 @@
import org.picketlink.identity.federation.core.wstrust.auth.STSIssuingLoginModule;
import org.picketlink.trust.jbossws.PicketLinkDispatch;
import org.picketlink.trust.jbossws.handler.BinaryTokenHandler;
+import org.picketlink.trust.jbossws.handler.MapBasedTokenHandler;
import org.picketlink.trust.jbossws.handler.SAML2Handler;
/**
@@ -74,10 +76,24 @@
}
@Override
- protected STSClient createWSTrustClient(STSClientConfig config)
- {
- return new JBWSTokenClient(config,options);
- }
+ protected STSClient createWSTrustClient(STSClientConfig config) {
+
+ String binaryTokenKey = (String) options
+ .get(MapBasedTokenHandler.SYS_PROP_TOKEN_KEY);
+ if (binaryTokenKey == null) {
+ binaryTokenKey = SecurityActions.getSystemProperty(
+ MapBasedTokenHandler.SYS_PROP_TOKEN_KEY,
+ MapBasedTokenHandler.DEFAULT_TOKEN_KEY);
+ }
+ Object binaryToken = sharedState.get(binaryTokenKey);
+
+ Map<String, ? super Object> STSClientOptions = new HashMap<String,
Object>(options);
+ if (binaryToken != null) {
+ STSClientOptions.put(binaryTokenKey, binaryToken);
+ }
+
+ return new JBWSTokenClient(config, STSClientOptions);
+ }
@SuppressWarnings("unchecked")
@Override
@@ -125,7 +141,7 @@
}
@SuppressWarnings("rawtypes")
- public JBWSTokenClient(STSClientConfig config, Map<String,?> options)
+ public JBWSTokenClient(STSClientConfig config, Map<String, ? super Object>
options)
{
super(config);
@@ -168,6 +184,10 @@
SAML2Handler samlHandler = new SAML2Handler();
handlers.add(samlHandler);
}
+ else if (token.equalsIgnoreCase("map")) {
+ MapBasedTokenHandler mapBasedHandler = new
MapBasedTokenHandler(options);
+ handlers.add(mapBasedHandler);
+ }
else
{
ClassLoader cl = SecurityActions.getClassLoader(getClass());