[picketlink-commits] Picketlink SVN: r389 - in federation/branches/Branch_1_x/picketlink-fed-core/src: main/java/org/picketlink/identity/federation/core/wstrust/wrappers and 2 other directories.
picketlink-commits at lists.jboss.org
picketlink-commits at lists.jboss.org
Mon Sep 6 21:27:16 EDT 2010
Author: sguilhen at redhat.com
Date: 2010-09-06 21:27:15 -0400 (Mon, 06 Sep 2010)
New Revision: 389
Modified:
federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/PicketLinkSTS.java
federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/StandardRequestHandler.java
federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustConstants.java
federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustJAXBFactory.java
federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustRequestHandler.java
federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java
federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/wrappers/RequestSecurityTokenCollection.java
federation/branches/Branch_1_x/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/saml/v2/X500AttributeUnitTestCase.java
federation/branches/Branch_1_x/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/wstrust/PicketLinkSTSUnitTestCase.java
Log:
PLFED-17: Added support for WS-Trust batch requests
Modified: federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/PicketLinkSTS.java
===================================================================
--- federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/PicketLinkSTS.java 2010-08-25 21:17:40 UTC (rev 388)
+++ federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/PicketLinkSTS.java 2010-09-07 01:27:15 UTC (rev 389)
@@ -1,23 +1,19 @@
/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, 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.
+ * JBoss, Home of Professional Open Source. Copyright 2009, 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.identity.federation.core.wstrust;
@@ -38,7 +34,6 @@
import org.apache.log4j.Logger;
import org.picketlink.identity.federation.core.config.STSType;
import org.picketlink.identity.federation.core.exceptions.ConfigurationException;
-import org.picketlink.identity.federation.core.saml.v2.common.SAMLDocumentHolder;
import org.picketlink.identity.federation.core.wstrust.wrappers.BaseRequestSecurityToken;
import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityToken;
import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityTokenCollection;
@@ -55,7 +50,7 @@
*/
@WebServiceProvider(serviceName = "PicketLinkSTS", portName = "PicketLinkSTSPort", targetNamespace = "urn:picketlink:identity-federation:sts", wsdlLocation = "WEB-INF/wsdl/PicketLinkSTS.wsdl")
@ServiceMode(value = Service.Mode.PAYLOAD)
-public class PicketLinkSTS implements Provider<Source>//SecurityTokenService
+public class PicketLinkSTS implements Provider<Source>// SecurityTokenService
{
private static Logger logger = Logger.getLogger(PicketLinkSTS.class);
@@ -77,6 +72,20 @@
*/
public Source invoke(Source request)
{
+ if (this.config == null)
+ {
+ try
+ {
+ if (logger.isInfoEnabled())
+ logger.info("Loading STS configuration");
+ this.config = this.getConfiguration();
+ }
+ catch (ConfigurationException e)
+ {
+ throw new WebServiceException("Encountered configuration exception:", e);
+ }
+ }
+
BaseRequestSecurityToken baseRequest;
try
{
@@ -106,25 +115,6 @@
*/
protected Source handleTokenRequest(RequestSecurityToken request)
{
- SAMLDocumentHolder holder = WSTrustJAXBFactory.getInstance().getSAMLDocumentHolderOnThread();
-
- /**
- * The RST Document is very important for XML Signatures
- */
- request.setRSTDocument(holder.getSamlDocument());
-
- if (this.config == null)
- try
- {
- if (logger.isInfoEnabled())
- logger.info("Loading STS configuration");
- this.config = this.getConfiguration();
- }
- catch (ConfigurationException e)
- {
- throw new WebServiceException("Encountered configuration exception:", e);
- }
-
WSTrustRequestHandler handler = this.config.getRequestHandler();
String requestType = request.getRequestType().toString();
if (logger.isDebugEnabled())
@@ -141,7 +131,6 @@
else if (requestType.equals(WSTrustConstants.RENEW_REQUEST))
{
Source source = this.marshallResponse(handler.renew(request, this.context.getUserPrincipal()));
- // we need to sign/encrypt renewed tokens.
Document document = handler.postProcess((Document) ((DOMSource) source).getNode(), request);
return new DOMSource(document);
}
@@ -168,7 +157,68 @@
*/
protected Source handleTokenRequestCollection(RequestSecurityTokenCollection requestCollection)
{
- throw new UnsupportedOperationException();
+ String requestType = requestCollection.getRequestSecurityTokens().get(0).getRequestType().toString();
+ if (logger.isDebugEnabled())
+ logger.debug("STS received requests of type " + requestType);
+ WSTrustRequestHandler handler = this.config.getRequestHandler();
+
+ try
+ {
+ if (requestType.equals(WSTrustConstants.BATCH_ISSUE_REQUEST))
+ {
+ // process each request at a time.
+ RequestSecurityTokenResponseCollection responseCollection = new RequestSecurityTokenResponseCollection();
+ for (RequestSecurityToken request : requestCollection.getRequestSecurityTokens())
+ responseCollection.addRequestSecurityTokenResponse(handler.issue(request, this.context
+ .getUserPrincipal()));
+ // marshal the whole response.
+ Source source = WSTrustJAXBFactory.getInstance().marshallRequestSecurityTokenResponse(responseCollection);
+ // post-process: sign and encrypt (if needed) all security tokens.
+ handler.postProcess((Document) ((DOMSource) source).getNode(), requestCollection.getRequestSecurityTokens()
+ .toArray(new RequestSecurityToken[0]));
+ return source;
+ }
+ else if (requestType.equals(WSTrustConstants.BATCH_RENEW_REQUEST))
+ {
+ // process each request at a time.
+ RequestSecurityTokenResponseCollection responseCollection = new RequestSecurityTokenResponseCollection();
+ for (RequestSecurityToken request : requestCollection.getRequestSecurityTokens())
+ responseCollection.addRequestSecurityTokenResponse(handler.renew(request, this.context
+ .getUserPrincipal()));
+ // marshal the whole response.
+ Source source = WSTrustJAXBFactory.getInstance().marshallRequestSecurityTokenResponse(responseCollection);
+ // post-process: sign and encrypt (if needed) all security tokens.
+ handler.postProcess((Document) ((DOMSource) source).getNode(), requestCollection.getRequestSecurityTokens()
+ .toArray(new RequestSecurityToken[0]));
+ return source;
+ }
+ else if (requestType.equals(WSTrustConstants.BATCH_CANCEL_REQUEST))
+ {
+ // process each request at a time.
+ RequestSecurityTokenResponseCollection responseCollection = new RequestSecurityTokenResponseCollection();
+ for (RequestSecurityToken request : requestCollection.getRequestSecurityTokens())
+ responseCollection.addRequestSecurityTokenResponse(handler.cancel(request, this.context
+ .getUserPrincipal()));
+ // marshal the whole response.
+ return WSTrustJAXBFactory.getInstance().marshallRequestSecurityTokenResponse(responseCollection);
+ }
+ else if (requestType.equals(WSTrustConstants.BATCH_VALIDATE_REQUEST))
+ {
+ // process each request at a time.
+ RequestSecurityTokenResponseCollection responseCollection = new RequestSecurityTokenResponseCollection();
+ for (RequestSecurityToken request : requestCollection.getRequestSecurityTokens())
+ responseCollection.addRequestSecurityTokenResponse(handler.validate(request, this.context
+ .getUserPrincipal()));
+ // marshal the whole response.
+ return WSTrustJAXBFactory.getInstance().marshallRequestSecurityTokenResponse(responseCollection);
+ }
+ else
+ throw new WSTrustException("Invalid request type: " + requestType);
+ }
+ catch (WSTrustException we)
+ {
+ throw new WebServiceException("Exception in handling token request: " + we.getMessage(), we);
+ }
}
/**
Modified: federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/StandardRequestHandler.java
===================================================================
--- federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/StandardRequestHandler.java 2010-08-25 21:17:40 UTC (rev 388)
+++ federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/StandardRequestHandler.java 2010-09-07 01:27:15 UTC (rev 389)
@@ -1,23 +1,19 @@
/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, 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.
+ * JBoss, Home of Professional Open Source. Copyright 2009, 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.identity.federation.core.wstrust;
@@ -55,6 +51,7 @@
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
/**
* <p>
@@ -305,7 +302,8 @@
public RequestSecurityTokenResponse renew(RequestSecurityToken request, Principal callerPrincipal)
throws WSTrustException
{
- // first validate the provided token signature to make sure it has been issued by this STS and hasn't been tempered.
+ // first validate the provided token signature to make sure it has been issued by this STS and hasn't been
+ // tempered.
if (trace)
log.trace("Validating token for renew request " + request.getContext());
if (request.getRenewTargetElement() == null)
@@ -352,6 +350,14 @@
log.debug("Lifetime has not been specified. Using the default timeout value.");
request.setLifetime(WSTrustUtil.createDefaultLifetime(this.configuration.getIssuedTokenTimeout()));
}
+ long keySize = request.getKeySize();
+ if (keySize == 0)
+ {
+ if (log.isDebugEnabled())
+ log.debug("No key size could be found in the request. Using the default size. (" + KEY_SIZE + ")");
+ keySize = KEY_SIZE;
+ request.setKeySize(keySize);
+ }
// create a context and dispatch to the proper security token provider for renewal.
WSTrustRequestContext context = new WSTrustRequestContext(request, callerPrincipal);
@@ -523,96 +529,102 @@
return response;
}
- public Document postProcess(Document rstrDocument, RequestSecurityToken request) throws WSTrustException
+ public Document postProcess(Document rstrDocument, RequestSecurityToken... requests) throws WSTrustException
{
- if (WSTrustConstants.ISSUE_REQUEST.equals(request.getRequestType().toString())
- || WSTrustConstants.RENEW_REQUEST.equals(request.getRequestType().toString()))
+ rstrDocument = DocumentUtil.normalizeNamespaces(rstrDocument);
+
+ // Sign all security tokens found in the document.
+ if (this.configuration.signIssuedToken() && this.configuration.getSTSKeyPair() != null)
{
- rstrDocument = DocumentUtil.normalizeNamespaces(rstrDocument);
-
- //Sign the security token
- if (this.configuration.signIssuedToken() && this.configuration.getSTSKeyPair() != null)
+ KeyPair keyPair = this.configuration.getSTSKeyPair();
+ NodeList nodes = rstrDocument
+ .getElementsByTagNameNS(WSTrustConstants.BASE_NAMESPACE, "RequestedSecurityToken");
+ if (nodes != null)
{
- KeyPair keyPair = this.configuration.getSTSKeyPair();
- URI signatureURI = request.getSignatureAlgorithm();
- String signatureMethod = signatureURI != null ? signatureURI.toString() : SignatureMethod.RSA_SHA1;
- try
+ for (int i = 0; i < nodes.getLength(); i++)
{
- Node rst = rstrDocument
- .getElementsByTagNameNS(WSTrustConstants.BASE_NAMESPACE, "RequestedSecurityToken").item(0);
- Element tokenElement = (Element) rst.getFirstChild();
+ Node node = nodes.item(i);
+ Element tokenElement = (Element) node.getFirstChild();
if (trace)
log.trace("NamespaceURI of element to be signed:" + tokenElement.getNamespaceURI());
- //Set the CanonicalizationMethod if any
- XMLSignatureUtil.setCanonicalizationMethodType( configuration.getXMLDSigCanonicalizationMethod() );
-
- rstrDocument = XMLSignatureUtil.sign(rstrDocument, tokenElement, keyPair, DigestMethod.SHA1,
- signatureMethod, "#" + tokenElement.getAttribute("ID"));
+ URI signatureURI = requests[i].getSignatureAlgorithm();
+ String signatureMethod = signatureURI != null ? signatureURI.toString() : SignatureMethod.RSA_SHA1;
+
+ // Set the CanonicalizationMethod if any
+ XMLSignatureUtil.setCanonicalizationMethodType(configuration.getXMLDSigCanonicalizationMethod());
+ try
+ {
+ rstrDocument = XMLSignatureUtil.sign(rstrDocument, tokenElement, keyPair, DigestMethod.SHA1,
+ signatureMethod, "#" + tokenElement.getAttribute("ID"));
+ }
+ catch (Exception e)
+ {
+ throw new WSTrustException("Failed to sign security token", e);
+ }
+
if (trace)
{
try
{
log.trace("Signed Token:" + DocumentUtil.getNodeAsString(tokenElement));
-
Document tokenDocument = DocumentUtil.createDocument();
tokenDocument.appendChild(tokenDocument.importNode(tokenElement, true));
log.trace("valid=" + XMLSignatureUtil.validate(tokenDocument, keyPair.getPublic()));
-
}
catch (Exception ignore)
{
}
}
}
- catch (Exception e)
- {
- throw new WSTrustException("Failed to sign security token", e);
- }
}
+ }
- // encrypt the security token if needed.
- if (this.configuration.encryptIssuedToken())
+ // encrypt all security tokens if needed.
+ if (this.configuration.encryptIssuedToken())
+ {
+ // encrypt the security tokens.
+ NodeList nodes = rstrDocument
+ .getElementsByTagNameNS(WSTrustConstants.BASE_NAMESPACE, "RequestedSecurityToken");
+ if (nodes != null)
{
- // get the public key that will be used to encrypt the token.
- PublicKey providerPublicKey = null;
- if (request.getAppliesTo() != null)
+ for (int i = 0; i < nodes.getLength(); i++)
{
- String serviceName = WSTrustUtil.parseAppliesTo(request.getAppliesTo());
- if (trace)
- log.trace("Locating public key for service provider " + serviceName);
- if (serviceName != null)
- providerPublicKey = this.configuration.getServiceProviderPublicKey(serviceName);
- }
- if (providerPublicKey == null)
- {
- log.warn("Security token should be encrypted but no encrypting key could be found");
- }
- else
- {
- // generate the secret key.
- long keySize = request.getKeySize();
- byte[] secret = WSTrustUtil.createRandomSecret((int) keySize / 8);
- SecretKey secretKey = new SecretKeySpec(secret, "AES");
-
- // encrypt the security token.
- Node rst = rstrDocument
- .getElementsByTagNameNS(WSTrustConstants.BASE_NAMESPACE, "RequestedSecurityToken").item(0);
- Element tokenElement = (Element) rst.getFirstChild();
- try
+ // get the public key that will be used to encrypt the token.
+ PublicKey providerPublicKey = null;
+ if (requests[i].getAppliesTo() != null)
{
- XMLEncryptionUtil.encryptElement(rstrDocument, tokenElement, providerPublicKey, secretKey,
- (int) keySize);
+ String serviceName = WSTrustUtil.parseAppliesTo(requests[i].getAppliesTo());
+ if (trace)
+ log.trace("Locating public key for service provider " + serviceName);
+ if (serviceName != null)
+ providerPublicKey = this.configuration.getServiceProviderPublicKey(serviceName);
}
- catch (ProcessingException e)
+ if (providerPublicKey == null)
{
- throw new WSTrustException("Unable to encrypt security token", e);
+ log.warn("Security token should be encrypted but no encrypting key could be found");
}
+ else
+ {
+ // generate the secret key.
+ long keySize = requests[i].getKeySize();
+ byte[] secret = WSTrustUtil.createRandomSecret((int) keySize / 8);
+ SecretKey secretKey = new SecretKeySpec(secret, "AES");
+
+ Element tokenElement = (Element) nodes.item(i).getFirstChild();
+ try
+ {
+ XMLEncryptionUtil.encryptElement(rstrDocument, tokenElement, providerPublicKey, secretKey,
+ (int) keySize);
+ }
+ catch (ProcessingException e)
+ {
+ throw new WSTrustException("Unable to encrypt security token", e);
+ }
+ }
}
}
}
-
return rstrDocument;
}
-
}
\ No newline at end of file
Modified: federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustConstants.java
===================================================================
--- federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustConstants.java 2010-08-25 21:17:40 UTC (rev 388)
+++ federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustConstants.java 2010-09-07 01:27:15 UTC (rev 389)
@@ -39,6 +39,10 @@
public static final String RENEW_REQUEST = BASE_NAMESPACE + "/Renew";
public static final String CANCEL_REQUEST = BASE_NAMESPACE + "/Cancel";
public static final String VALIDATE_REQUEST = BASE_NAMESPACE + "/Validate";
+ public static final String BATCH_ISSUE_REQUEST = BASE_NAMESPACE + "/BatchIssue";
+ public static final String BATCH_RENEW_REQUEST = BASE_NAMESPACE + "/BatchRenew";
+ public static final String BATCH_CANCEL_REQUEST = BASE_NAMESPACE + "/BatchCancel";
+ public static final String BATCH_VALIDATE_REQUEST = BASE_NAMESPACE + "/BatchValidate";
// WS-Trust validation constants.
public static final String STATUS_TYPE = BASE_NAMESPACE + "/RSTR/Status";
Modified: federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustJAXBFactory.java
===================================================================
--- federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustJAXBFactory.java 2010-08-25 21:17:40 UTC (rev 388)
+++ federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustJAXBFactory.java 2010-09-07 01:27:15 UTC (rev 389)
@@ -1,31 +1,29 @@
/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, 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.
+ * JBoss, Home of Professional Open Source. Copyright 2009, 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.identity.federation.core.wstrust;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.xml.bind.Binder;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
import javax.xml.transform.Source;
import org.apache.log4j.Logger;
@@ -35,9 +33,11 @@
import org.picketlink.identity.federation.core.wstrust.wrappers.BaseRequestSecurityToken;
import org.picketlink.identity.federation.core.wstrust.wrappers.BaseRequestSecurityTokenResponse;
import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityToken;
+import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityTokenCollection;
import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityTokenResponse;
import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityTokenResponseCollection;
import org.picketlink.identity.federation.ws.trust.ObjectFactory;
+import org.picketlink.identity.federation.ws.trust.RequestSecurityTokenCollectionType;
import org.picketlink.identity.federation.ws.trust.RequestSecurityTokenResponseCollectionType;
import org.picketlink.identity.federation.ws.trust.RequestSecurityTokenType;
import org.w3c.dom.Document;
@@ -62,8 +62,6 @@
private Marshaller marshaller;
- private Unmarshaller unmarshaller;
-
private Binder<Node> binder;
private final ObjectFactory objectFactory;
@@ -80,7 +78,6 @@
try
{
this.marshaller = JAXBUtil.getMarshaller(this.getPackages());
- this.unmarshaller = JAXBUtil.getUnmarshaller(this.getPackages());
this.binder = JAXBUtil.getJAXBContext(this.getPackages()).createBinder();
this.objectFactory = new ObjectFactory();
}
@@ -119,34 +116,39 @@
* Creates a {@code BaseRequestSecurityToken} from the specified XML source.
* </p>
*
- * @param request
- * the XML source containing the security token request message.
+ * @param request the XML source containing the security token request message.
* @return the constructed {@code BaseRequestSecurityToken} instance. It will be an instance of {@code
* RequestSecurityToken} the message contains a single token request, and an instance of {@code
* RequestSecurityTokenCollection} if multiples requests are being made in the same message.
*/
- @SuppressWarnings("unchecked")
public BaseRequestSecurityToken parseRequestSecurityToken(Source request) throws WSTrustException
{
- // if the request contains a validate, cancel, or renew target, we must preserve it from JAXB unmarshalling.
try
{
Node documentNode = DocumentUtil.getNodeFromSource(request);
Document document = documentNode instanceof Document ? (Document) documentNode : documentNode
.getOwnerDocument();
-
- JAXBElement<RequestSecurityTokenType> jaxbRST;
Node rst = this.findNodeByNameNS(document, "RequestSecurityToken", WSTrustConstants.BASE_NAMESPACE);
if (rst == null)
- throw new RuntimeException("Request Security Token node not found");
+ throw new RuntimeException("The request document must contain at least one RequestSecurityToken node");
- jaxbRST = (JAXBElement<RequestSecurityTokenType>) binder.unmarshal(rst);
-
- RequestSecurityTokenType rstt = jaxbRST.getValue();
-
- SAML2SecurityToken samlSecurityToken = new SAML2SecurityToken(rstt);
- holders.set(new SAMLDocumentHolder(samlSecurityToken, document));
- return new RequestSecurityToken(rstt);
+ JAXBElement<?> jaxbRST = (JAXBElement<?>) binder.unmarshal(document);
+ if (jaxbRST.getDeclaredType().equals(RequestSecurityTokenType.class))
+ {
+ RequestSecurityTokenType rstt = (RequestSecurityTokenType) jaxbRST.getValue();
+ RequestSecurityToken requestSecToken = new RequestSecurityToken(rstt);
+ requestSecToken.setRSTDocument(document);
+ return requestSecToken;
+ }
+ else if (jaxbRST.getDeclaredType().equals(RequestSecurityTokenCollectionType.class))
+ {
+ RequestSecurityTokenCollectionType rstct = (RequestSecurityTokenCollectionType) jaxbRST.getValue();
+ RequestSecurityTokenCollection requestSecTokenCollection = new RequestSecurityTokenCollection(rstct,
+ document);
+ return requestSecTokenCollection;
+ }
+ else
+ throw new WSTrustException("Request message doesn't contain a valid request type");
}
catch (Exception e)
{
@@ -159,16 +161,13 @@
* Creates a {@code BaseRequestSecurityTokenResponse} from the specified XML source.
* </p>
*
- * @param response
- * the XML source containing the security token response message.
+ * @param response the XML source containing the security token response message.
* @return the constructed {@code BaseRequestSecurityTokenResponse} instance. According to the WS-Trust
* specification, the returned object will be an instance of {@code RequestSecurityTokenResponseCollection}.
*/
@SuppressWarnings("unchecked")
public BaseRequestSecurityTokenResponse parseRequestSecurityTokenResponse(Source response) throws WSTrustException
{
- // if the response contains an issued token, we must preserve it from the JAXB unmarshalling.
- Element tokenElement = null;
Node documentNode = null;
try
{
@@ -179,15 +178,9 @@
throw new WSTrustException("Failed to transform request source", e);
}
- Document document = documentNode instanceof Document ? (Document) documentNode : documentNode.getOwnerDocument();
- Node requestedTokenNode = this.findNodeByNameNS(document, "RequestedSecurityToken",
- WSTrustConstants.BASE_NAMESPACE);
- if (requestedTokenNode != null)
- tokenElement = (Element) requestedTokenNode.getFirstChild();
-
try
{
- Object object = this.unmarshaller.unmarshal(documentNode);
+ Object object = this.binder.unmarshal(documentNode);
if (object instanceof JAXBElement)
{
JAXBElement<?> element = (JAXBElement<?>) object;
@@ -195,12 +188,6 @@
{
RequestSecurityTokenResponseCollection collection = new RequestSecurityTokenResponseCollection(
(RequestSecurityTokenResponseCollectionType) element.getValue());
- // insert the security token in the parsed response.
- if (tokenElement != null)
- {
- RequestSecurityTokenResponse parsedResponse = collection.getRequestSecurityTokenResponses().get(0);
- parsedResponse.getRequestedSecurityToken().setAny(tokenElement);
- }
return collection;
}
else
@@ -220,8 +207,7 @@
* Creates a {@code javax.xml.transform.Source} from the specified request object.
* </p>
*
- * @param request
- * a {@code RequestSecurityToken} representing the object model of the security token request.
+ * @param request a {@code RequestSecurityToken} representing the object model of the security token request.
* @return the constructed {@code Source} instance.
*/
public Source marshallRequestSecurityToken(RequestSecurityToken request)
@@ -249,9 +235,9 @@
try
{
result = DocumentUtil.createDocument();
- this.marshaller.marshal(this.objectFactory.createRequestSecurityToken(request.getDelegate()), result);
+ this.binder.marshal(this.objectFactory.createRequestSecurityToken(request.getDelegate()), result);
- // insert the original target in the appropriate element.
+ // insert the original target in the appropriate element.
if (targetElement != null)
{
Node node = null;
@@ -276,12 +262,101 @@
/**
* <p>
+ * Creates a {@code javax.xml.transform.Source} from the specified request object.
+ * </p>
+ *
+ * @param request a {@code RequestSecurityTokenCollection} representing the object model of the security token batch
+ * request.
+ * @return the constructed {@code Source} instance.
+ */
+ public Source marshallRequestSecurityTokenCollection(RequestSecurityTokenCollection collection)
+ {
+ // validation: the collection must contain at least one request.
+ if (collection == null || collection.getRequestSecurityTokens().size() == 0)
+ throw new IllegalArgumentException("The request collection must contain at least one request");
+
+ // validation: all requests must be the of the same type and must match one of the batch request types.
+ String requestType = null;
+ for (RequestSecurityToken request : collection.getRequestSecurityTokens())
+ {
+ // this is the first request: ensure its type is valid.
+ if (requestType == null)
+ {
+ if (request.getRequestType() == null || !isValidBatchRequestType(request.getRequestType().toString()))
+ throw new IllegalArgumentException(
+ "The request type cannot be null and must be a valid WS-Trust batch request type");
+ requestType = request.getRequestType().toString();
+ }
+ // for the other requests, ensure their type matches the type of the first request.
+ else
+ {
+ if (request.getRequestType() == null || !requestType.equals(request.getRequestType().toString()))
+ throw new IllegalArgumentException("All requests must be of the same type. Invalid type: "
+ + request.getRequestType());
+ }
+ }
+
+ // save the cancel/renew/validate targets to preserve them from the JAXB marshaling process.
+ List<Element> targets = new ArrayList<Element>();
+ for (RequestSecurityToken request : collection.getRequestSecurityTokens())
+ {
+ if (requestType.equals(WSTrustConstants.BATCH_CANCEL_REQUEST))
+ {
+ targets.add((Element) request.getCancelTarget().getAny());
+ request.getCancelTarget().setAny(null);
+ }
+ else if (requestType.equals(WSTrustConstants.BATCH_RENEW_REQUEST))
+ {
+ targets.add((Element) request.getRenewTarget().getAny());
+ request.getRenewTarget().setAny(null);
+ }
+ else if (requestType.equals(WSTrustConstants.BATCH_VALIDATE_REQUEST))
+ {
+ targets.add((Element) request.getValidateTarget().getAny());
+ request.getValidateTarget().setAny(null);
+ }
+ }
+
+ // marshal the document and reinsert the target elements in the generated XML document.
+ Document result = null;
+ try
+ {
+ result = DocumentUtil.createDocument();
+ this.binder.marshal(this.objectFactory.createRequestSecurityTokenCollection(collection.getDelegate()), result);
+
+ NodeList nodes = null;
+ if (requestType.equals(WSTrustConstants.BATCH_CANCEL_REQUEST))
+ nodes = result.getElementsByTagNameNS(WSTrustConstants.BASE_NAMESPACE, "CancelTarget");
+ else if (requestType.equals(WSTrustConstants.BATCH_RENEW_REQUEST))
+ nodes = result.getElementsByTagNameNS(WSTrustConstants.BASE_NAMESPACE, "RenewTarget");
+ else if (requestType.equals(WSTrustConstants.BATCH_VALIDATE_REQUEST))
+ nodes = result.getElementsByTagNameNS(WSTrustConstants.BASE_NAMESPACE, "ValidateTarget");
+
+ // iterate through the document nodes reinserting the original target elements.
+ if (nodes != null)
+ {
+ for (int i = 0; i < nodes.getLength(); i++)
+ {
+ Node node = nodes.item(i);
+ node.appendChild(result.importNode(targets.get(i), true));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Failed to marshall security token request", e);
+ }
+
+ return DocumentUtil.getXMLSource(result);
+ }
+
+ /**
+ * <p>
* Creates a {@code javax.xml.transform.Source} from the specified response object.
* </p>
*
- * @param collection
- * a {@code RequestSecurityTokenResponseCollection} representing the object model of the security token
- * response.
+ * @param collection a {@code RequestSecurityTokenResponseCollection} representing the object model of the security
+ * token response.
* @return the constructed {@code Source} instance.
*/
public Source marshallRequestSecurityTokenResponse(RequestSecurityTokenResponseCollection collection)
@@ -289,29 +364,35 @@
if (collection.getRequestSecurityTokenResponses().size() == 0)
throw new IllegalArgumentException("The response collection must contain at least one response");
- // if the response contains an issued token, we must preserve it from the JAXB marshaling.
- Element tokenElement = null;
- RequestSecurityTokenResponse response = collection.getRequestSecurityTokenResponses().get(0);
- if (response.getRequestedSecurityToken() != null)
+ // if the response contains issued tokens, we must preserve them from the JAXB marshaling.
+ List<Element> tokenElements = new ArrayList<Element>();
+ for (RequestSecurityTokenResponse response : collection.getRequestSecurityTokenResponses())
{
- tokenElement = (Element) response.getRequestedSecurityToken().getAny();
- // we don't want to marshall any token - it will be inserted in the DOM document later.
- response.getRequestedSecurityToken().setAny(null);
+ if (response.getRequestedSecurityToken() != null)
+ {
+ tokenElements.add((Element) response.getRequestedSecurityToken().getAny());
+ // we don't want to marshall any token - it will be inserted in the DOM document later.
+ response.getRequestedSecurityToken().setAny(null);
+ }
}
Document result = null;
try
{
- // marshall the response to a document and insert the issued token directly on the document.
+ // marshall the response to a document and insert the issued tokens directly into the document.
result = DocumentUtil.createDocument();
this.marshaller.marshal(this.objectFactory.createRequestSecurityTokenResponseCollection(collection
.getDelegate()), result);
- // the document is a ws-trust template - we need to insert the token in the appropriate element.
- if (tokenElement != null)
+ // the document is a ws-trust template - we need to insert the tokens in the appropriate elements.
+ if (!tokenElements.isEmpty())
{
- Node node = this.findNodeByNameNS(result, "RequestedSecurityToken", WSTrustConstants.BASE_NAMESPACE);
- node.appendChild(result.importNode(tokenElement, true));
+ NodeList nodes = result.getElementsByTagNameNS(WSTrustConstants.BASE_NAMESPACE, "RequestedSecurityToken");
+ for (int i = 0; i < nodes.getLength(); i++)
+ {
+ Node node = nodes.item(i);
+ node.appendChild(result.importNode(tokenElements.get(i), true));
+ }
}
if (trace)
{
@@ -328,6 +409,7 @@
/**
* Return the {@code SAMLDocumentHolder} for the thread
+ *
* @return
*/
public SAMLDocumentHolder getSAMLDocumentHolderOnThread()
@@ -340,12 +422,9 @@
* Finds in the specified document a node that matches the specified name and namespace.
* </p>
*
- * @param document
- * the {@code Document} instance upon which the search is made.
- * @param localName
- * a {@code String} containing the local name of the searched node.
- * @param namespace
- * a {@code String} containing the namespace of the searched node.
+ * @param document the {@code Document} instance upon which the search is made.
+ * @param localName a {@code String} containing the local name of the searched node.
+ * @param namespace a {@code String} containing the namespace of the searched node.
* @return a {@code Node} representing the searched node. If more than one node is found in the document, the first
* one will be returned. If no nodes were found according to the search parameters, then {@code null} is
* returned.
@@ -359,4 +438,20 @@
return list.item(0);
}
+ /**
+ * <p>
+ * Verifies if the specified {@code String} represents one of the valid WS-Trust batch request types or not.
+ * </p>
+ *
+ * @param requestType the {@code String} to be verified.
+ * @return {@code true} if the request type matches one of the WS-Trust batch requests; {@code false} otherwise.
+ */
+ private boolean isValidBatchRequestType(String requestType)
+ {
+ // the request type must match one of the WS-Trust batch request types.
+ return (requestType.equals(WSTrustConstants.BATCH_ISSUE_REQUEST)
+ || requestType.equals(WSTrustConstants.BATCH_RENEW_REQUEST)
+ || requestType.equals(WSTrustConstants.BATCH_CANCEL_REQUEST) || requestType
+ .equals(WSTrustConstants.BATCH_VALIDATE_REQUEST));
+ }
}
\ No newline at end of file
Modified: federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustRequestHandler.java
===================================================================
--- federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustRequestHandler.java 2010-08-25 21:17:40 UTC (rev 388)
+++ federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustRequestHandler.java 2010-09-07 01:27:15 UTC (rev 389)
@@ -107,5 +107,5 @@
* @return
* @throws WSTrustException
*/
- public Document postProcess(Document rstrDocument, RequestSecurityToken request) throws WSTrustException;
+ public Document postProcess(Document rstrDocument, RequestSecurityToken... requests) throws WSTrustException;
}
Modified: federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java
===================================================================
--- federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java 2010-08-25 21:17:40 UTC (rev 388)
+++ federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java 2010-09-07 01:27:15 UTC (rev 389)
@@ -272,17 +272,6 @@
}
/**
- * Creates an instance of {@code RequestSecurityTokenType} and {@code Document}
- * @param delegate
- * @param rstDocument
- */
- public RequestSecurityToken(RequestSecurityTokenType delegate, Document rstDocument)
- {
- this(delegate);
- this.rstDocument = rstDocument;
- }
-
- /**
* <p>
* Obtains the {@code URI} that identifies the token type.
* </p>
Modified: federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/wrappers/RequestSecurityTokenCollection.java
===================================================================
--- federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/wrappers/RequestSecurityTokenCollection.java 2010-08-25 21:17:40 UTC (rev 388)
+++ federation/branches/Branch_1_x/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/wrappers/RequestSecurityTokenCollection.java 2010-09-07 01:27:15 UTC (rev 389)
@@ -1,23 +1,19 @@
/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, 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.
+ * JBoss, Home of Professional Open Source. Copyright 2009, 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.identity.federation.core.wstrust.wrappers;
@@ -25,8 +21,13 @@
import java.util.Collections;
import java.util.List;
+import org.picketlink.identity.federation.core.exceptions.ConfigurationException;
+import org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil;
+import org.picketlink.identity.federation.core.wstrust.WSTrustConstants;
import org.picketlink.identity.federation.ws.trust.RequestSecurityTokenCollectionType;
import org.picketlink.identity.federation.ws.trust.RequestSecurityTokenType;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
/**
* <p>
@@ -71,6 +72,40 @@
/**
* <p>
+ * Creates an instance of {@code RequestSecurityTokenCollection} using the specified delegate and document.
+ * </p>
+ *
+ * @param delegate the JAXB {@code RequestSecurityTokenCollectionType} that represents a WS-Trust request collection.
+ * @param document the {@code Document} that contains the original WS-Trust batch request message.
+ */
+ public RequestSecurityTokenCollection(RequestSecurityTokenCollectionType delegate, Document document)
+ {
+ this.delegate = delegate;
+ this.requestSecurityTokens = new ArrayList<RequestSecurityToken>();
+ for (RequestSecurityTokenType request : delegate.getRequestSecurityToken())
+ this.requestSecurityTokens.add(new RequestSecurityToken(request));
+
+ // retrieve a list of the individual request nodes.
+ NodeList list = document.getElementsByTagNameNS(WSTrustConstants.BASE_NAMESPACE, "RequestSecurityToken");
+
+ // iterate through the nodes and set each node in its respective request object.
+ try
+ {
+ for (int i = 0; i < list.getLength(); i++)
+ {
+ Document doc = DocumentUtil.createDocument();
+ doc.appendChild(doc.importNode(list.item(i), true));
+ this.requestSecurityTokens.get(i).setRSTDocument(doc);
+ }
+ }
+ catch (ConfigurationException ce)
+ {
+ throw new RuntimeException("Error creating document: " + ce.getMessage(), ce);
+ }
+ }
+
+ /**
+ * <p>
* Obtains the collection of {@code RequestSecurityToken} objects. The returned collection is immutable, so addition
* or removal of requests must be carried by the appropriate add/remove methods.
* </p>
@@ -94,7 +129,7 @@
this.delegate.getRequestSecurityToken().add(request.getDelegate());
this.requestSecurityTokens.add(request);
}
-
+
/**
* <p>
* Removes the specified {@code RequestSecurityToken} object from the collection of token requests.
@@ -107,7 +142,7 @@
this.delegate.getRequestSecurityToken().remove(request.getDelegate());
this.requestSecurityTokens.remove(request);
}
-
+
/**
* <p>
* Obtains a reference to the {@code RequestSecurityTokenCollectionType} delegate.
Modified: federation/branches/Branch_1_x/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/saml/v2/X500AttributeUnitTestCase.java
===================================================================
--- federation/branches/Branch_1_x/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/saml/v2/X500AttributeUnitTestCase.java 2010-08-25 21:17:40 UTC (rev 388)
+++ federation/branches/Branch_1_x/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/saml/v2/X500AttributeUnitTestCase.java 2010-09-07 01:27:15 UTC (rev 389)
@@ -84,7 +84,7 @@
//marshaller.marshal(jaxb, System.out);
Document samlDom = DocumentUtil.getDocument(new String(baos.toByteArray()));
- NodeList nl = samlDom.getElementsByTagName("Attribute");
+ NodeList nl = samlDom.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Attribute");
assertEquals("nodes = 2", 2, nl.getLength());
String x500NS = JBossSAMLURIConstants.X500_NSURI.get();
Modified: federation/branches/Branch_1_x/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/wstrust/PicketLinkSTSUnitTestCase.java
===================================================================
--- federation/branches/Branch_1_x/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/wstrust/PicketLinkSTSUnitTestCase.java 2010-08-25 21:17:40 UTC (rev 388)
+++ federation/branches/Branch_1_x/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/wstrust/PicketLinkSTSUnitTestCase.java 2010-09-07 01:27:15 UTC (rev 389)
@@ -62,6 +62,7 @@
import org.picketlink.identity.federation.core.wstrust.wrappers.BaseRequestSecurityTokenResponse;
import org.picketlink.identity.federation.core.wstrust.wrappers.Lifetime;
import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityToken;
+import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityTokenCollection;
import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityTokenResponse;
import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityTokenResponseCollection;
import org.picketlink.identity.federation.saml.v2.assertion.AssertionType;
@@ -254,7 +255,11 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- this.validateCustomTokenResponse(baseResponse);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ this.validateCustomTokenResponse(collection.getRequestSecurityTokenResponses().get(0), "testcontext");
}
/**
@@ -310,7 +315,12 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke", SAMLUtil.SAML2_BEARER_URI);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ this.validateSAMLAssertionResponse(collection.getRequestSecurityTokenResponses().get(0), "testcontext", "jduke",
+ SAMLUtil.SAML2_BEARER_URI);
}
/**
@@ -338,7 +348,11 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- this.validateCustomTokenResponse(baseResponse);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ this.validateCustomTokenResponse(collection.getRequestSecurityTokenResponses().get(0), "testcontext");
}
/**
@@ -365,8 +379,12 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke",
- SAMLUtil.SAML2_BEARER_URI);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ AssertionType assertion = this.validateSAMLAssertionResponse(
+ collection.getRequestSecurityTokenResponses().get(0), "testcontext", "jduke", SAMLUtil.SAML2_BEARER_URI);
// in this scenario, the conditions section should have an audience restriction.
ConditionsType conditions = assertion.getConditions();
@@ -407,7 +425,12 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response (assertion principal should be anotherduke as specified by OnBehalfOf).
- this.validateSAMLAssertionResponse(baseResponse, "testcontext", "anotherduke", SAMLUtil.SAML2_SENDER_VOUCHES_URI);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ this.validateSAMLAssertionResponse(collection.getRequestSecurityTokenResponses().get(0), "testcontext",
+ "anotherduke", SAMLUtil.SAML2_SENDER_VOUCHES_URI);
}
/**
@@ -439,7 +462,12 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke",
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ AssertionType assertion = this.validateSAMLAssertionResponse(
+ collection.getRequestSecurityTokenResponses().get(0), "testcontext", "jduke",
SAMLUtil.SAML2_HOLDER_OF_KEY_URI);
// validate the holder of key contents.
SubjectConfirmationType subjConfirmation = (SubjectConfirmationType) assertion.getSubject().getContent().get(1)
@@ -447,7 +475,7 @@
this.validateHolderOfKeyContents(subjConfirmation, WSTrustConstants.KEY_TYPE_SYMMETRIC, null, false);
// check if the response contains the STS-generated key.
- RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ collection = (RequestSecurityTokenResponseCollection) baseResponse;
RequestSecurityTokenResponse response = collection.getRequestSecurityTokenResponses().get(0);
RequestedProofTokenType proofToken = response.getRequestedProofToken();
assertNotNull("Unexpected null proof token", proofToken);
@@ -498,14 +526,19 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke",
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ AssertionType assertion = this.validateSAMLAssertionResponse(
+ collection.getRequestSecurityTokenResponses().get(0), "testcontext", "jduke",
SAMLUtil.SAML2_HOLDER_OF_KEY_URI);
// validate the holder of key contents.
SubjectConfirmationType subjConfirmation = (SubjectConfirmationType) assertion.getSubject().getContent().get(1)
.getValue();
this.validateHolderOfKeyContents(subjConfirmation, WSTrustConstants.KEY_TYPE_SYMMETRIC, null, false);
- RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ collection = (RequestSecurityTokenResponseCollection) baseResponse;
RequestSecurityTokenResponse response = collection.getRequestSecurityTokenResponses().get(0);
RequestedProofTokenType proofToken = response.getRequestedProofToken();
assertNotNull("Unexpected null proof token", proofToken);
@@ -558,7 +591,12 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke",
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ AssertionType assertion = this.validateSAMLAssertionResponse(
+ collection.getRequestSecurityTokenResponses().get(0), "testcontext", "jduke",
SAMLUtil.SAML2_HOLDER_OF_KEY_URI);
// validate the holder of key contents.
SubjectConfirmationType subjConfirmation = (SubjectConfirmationType) assertion.getSubject().getContent().get(1)
@@ -595,7 +633,12 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke",
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ AssertionType assertion = this.validateSAMLAssertionResponse(
+ collection.getRequestSecurityTokenResponses().get(0), "testcontext", "jduke",
SAMLUtil.SAML2_HOLDER_OF_KEY_URI);
// validate the holder of key contents.
SubjectConfirmationType subjConfirmation = (SubjectConfirmationType) assertion.getSubject().getContent().get(1)
@@ -617,7 +660,7 @@
RequestSecurityToken request = this.createRequest("testcontext", WSTrustConstants.ISSUE_REQUEST,
SAMLUtil.SAML2_TOKEN_TYPE, null);
- // use the factory to marshall the request.
+ // use the factory to marshal the request.
WSTrustJAXBFactory factory = WSTrustJAXBFactory.getInstance();
Source requestMessage = factory.marshallRequestSecurityToken(request);
@@ -626,8 +669,13 @@
BaseRequestSecurityTokenResponse baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
// validate the response and get the SAML assertion from the request.
- this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke", SAMLUtil.SAML2_BEARER_URI);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ this.validateSAMLAssertionResponse(collection.getRequestSecurityTokenResponses().get(0), "testcontext", "jduke",
+ SAMLUtil.SAML2_BEARER_URI);
+
Element assertion = (Element) collection.getRequestSecurityTokenResponses().get(0).getRequestedSecurityToken()
.getAny();
@@ -685,7 +733,7 @@
RequestSecurityToken request = this.createRequest("testcontext", WSTrustConstants.ISSUE_REQUEST, null,
"http://services.testcorp.org/provider2");
- // use the factory to marshall the request.
+ // use the factory to marshal the request.
WSTrustJAXBFactory factory = WSTrustJAXBFactory.getInstance();
Source requestMessage = factory.marshallRequestSecurityToken(request);
@@ -694,8 +742,12 @@
BaseRequestSecurityTokenResponse baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
// validate the response and get the SAML assertion from the request.
- this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke", SAMLUtil.SAML2_BEARER_URI);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ this.validateSAMLAssertionResponse(collection.getRequestSecurityTokenResponses().get(0), "testcontext", "jduke",
+ SAMLUtil.SAML2_BEARER_URI);
Element assertionElement = (Element) collection.getRequestSecurityTokenResponses().get(0)
.getRequestedSecurityToken().getAny();
@@ -710,8 +762,13 @@
baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
// validate the renew response contents and get the renewed token.
- this.validateSAMLAssertionResponse(baseResponse, "renewcontext", "jduke", SAMLUtil.SAML2_BEARER_URI);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ this.validateSAMLAssertionResponse(collection.getRequestSecurityTokenResponses().get(0), "renewcontext", "jduke",
+ SAMLUtil.SAML2_BEARER_URI);
+ collection = (RequestSecurityTokenResponseCollection) baseResponse;
Element renewedAssertionElement = (Element) collection.getRequestSecurityTokenResponses().get(0)
.getRequestedSecurityToken().getAny();
@@ -742,7 +799,7 @@
RequestSecurityToken request = this.createRequest("testcontext", WSTrustConstants.ISSUE_REQUEST,
SAMLUtil.SAML2_TOKEN_TYPE, null);
- // use the factory to marshall the request.
+ // use the factory to marshal the request.
WSTrustJAXBFactory factory = WSTrustJAXBFactory.getInstance();
Source requestMessage = factory.marshallRequestSecurityToken(request);
@@ -751,8 +808,12 @@
BaseRequestSecurityTokenResponse baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
// validate the response and get the SAML assertion from the request.
- this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke", SAMLUtil.SAML2_BEARER_URI);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
+ this.validateSAMLAssertionResponse(collection.getRequestSecurityTokenResponses().get(0), "testcontext", "jduke",
+ SAMLUtil.SAML2_BEARER_URI);
Element assertion = (Element) collection.getRequestSecurityTokenResponses().get(0).getRequestedSecurityToken()
.getAny();
@@ -817,6 +878,413 @@
/**
* <p>
+ * This test sends a {@code BatchIssue} request to the STS in an attempt to generate two different security tokens
+ * using a single WS-Trust request message.
+ * </p>
+ *
+ * @throws Exception if an error occurs while running the test.
+ */
+ public void testBatchIssue() throws Exception
+ {
+ // create two issue requests - in this case the user wants two different tokens from the STS.
+ RequestSecurityToken request1 = this.createRequest("context1", WSTrustConstants.BATCH_ISSUE_REQUEST,
+ SAMLUtil.SAML2_TOKEN_TYPE, null);
+ RequestSecurityToken request2 = this.createRequest("context2", WSTrustConstants.BATCH_ISSUE_REQUEST,
+ "http://www.tokens.org/SpecialToken", null);
+
+ // create a request collection that includes the two issue requests.
+ RequestSecurityTokenCollection collection = new RequestSecurityTokenCollection();
+ collection.addRequestSecurityToken(request1);
+ collection.addRequestSecurityToken(request2);
+
+ // use the factory to marshal the request collection.
+ WSTrustJAXBFactory factory = WSTrustJAXBFactory.getInstance();
+ Source requestMessage = factory.marshallRequestSecurityTokenCollection(collection);
+
+ // invoke the token service.
+ Source responseMessage = this.tokenService.invoke(requestMessage);
+
+ // validate the overall response.
+ BaseRequestSecurityTokenResponse baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection responseCollection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 2, responseCollection.getRequestSecurityTokenResponses().size());
+
+ // first response should contain a SAML assertion.
+ this.validateSAMLAssertionResponse(responseCollection.getRequestSecurityTokenResponses().get(0), "context1",
+ "jduke", SAMLUtil.SAML2_BEARER_URI);
+
+ // second response should contain a custom token.
+ this.validateCustomTokenResponse(responseCollection.getRequestSecurityTokenResponses().get(1), "context2");
+ }
+
+ /**
+ * <p>
+ * This test sends a {@code BatchValidate} request to the STS in an attempt to validate two different security tokens
+ * using a single WS-Trust request message.
+ * </p>
+ *
+ * @throws Exception if an error occurs while running the test.
+ */
+ public void testBatchValidate() throws Exception
+ {
+ // first issue two assertions, one using the token type and the other using applies to.
+ RequestSecurityToken request1 = this.createRequest("context1", WSTrustConstants.BATCH_ISSUE_REQUEST,
+ SAMLUtil.SAML2_TOKEN_TYPE, null);
+ RequestSecurityToken request2 = this.createRequest("context2", WSTrustConstants.BATCH_ISSUE_REQUEST, null,
+ "http://services.testcorp.org/provider2");
+
+ // create a request collection that includes the two issue requests.
+ RequestSecurityTokenCollection collection = new RequestSecurityTokenCollection();
+ collection.addRequestSecurityToken(request1);
+ collection.addRequestSecurityToken(request2);
+
+ // use the factory to marshal the request collection.
+ WSTrustJAXBFactory factory = WSTrustJAXBFactory.getInstance();
+ Source requestMessage = factory.marshallRequestSecurityTokenCollection(collection);
+
+ // invoke the token service.
+ Source responseMessage = this.tokenService.invoke(requestMessage);
+
+ // validate the response and get the SAML assertions from the request.
+ BaseRequestSecurityTokenResponse baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection responseCollection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 2, responseCollection.getRequestSecurityTokenResponses().size());
+
+ Element assertion1 = (Element) responseCollection.getRequestSecurityTokenResponses().get(0)
+ .getRequestedSecurityToken().getAny();
+ Element assertion2 = (Element) responseCollection.getRequestSecurityTokenResponses().get(1)
+ .getRequestedSecurityToken().getAny();
+
+ // now construct a WS-Trust batch validate request with the generated assertion.
+ request1 = this.createRequest("validatecontext1", WSTrustConstants.BATCH_VALIDATE_REQUEST,
+ WSTrustConstants.STATUS_TYPE, null);
+ ValidateTargetType validateTarget1 = new ValidateTargetType();
+ validateTarget1.setAny(assertion1);
+ request1.setValidateTarget(validateTarget1);
+
+ request2 = this.createRequest("validatecontext2", WSTrustConstants.BATCH_VALIDATE_REQUEST,
+ WSTrustConstants.STATUS_TYPE, null);
+ ValidateTargetType validateTarget2 = new ValidateTargetType();
+ validateTarget2.setAny(assertion2);
+ request2.setValidateTarget(validateTarget2);
+
+ collection = new RequestSecurityTokenCollection();
+ collection.addRequestSecurityToken(request1);
+ collection.addRequestSecurityToken(request2);
+
+ // invoke the token service.
+ responseMessage = this.tokenService.invoke(factory.marshallRequestSecurityTokenCollection(collection));
+
+ // check the validation response.
+ baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ responseCollection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 2, responseCollection.getRequestSecurityTokenResponses().size());
+
+ RequestSecurityTokenResponse response = responseCollection.getRequestSecurityTokenResponses().get(0);
+ assertEquals("Unexpected response context", "validatecontext1", response.getContext());
+ assertEquals("Unexpected token type", WSTrustConstants.STATUS_TYPE, response.getTokenType().toString());
+ StatusType status = response.getStatus();
+ assertNotNull("Unexpected null status", status);
+ assertEquals("Unexpected status code", WSTrustConstants.STATUS_CODE_VALID, status.getCode());
+ assertEquals("Unexpected status reason", "SAMLV2.0 Assertion successfuly validated", status.getReason());
+
+ response = responseCollection.getRequestSecurityTokenResponses().get(1);
+ assertEquals("Unexpected response context", "validatecontext2", response.getContext());
+ assertEquals("Unexpected token type", WSTrustConstants.STATUS_TYPE, response.getTokenType().toString());
+ status = response.getStatus();
+ assertNotNull("Unexpected null status", status);
+ assertEquals("Unexpected status code", WSTrustConstants.STATUS_CODE_VALID, status.getCode());
+ assertEquals("Unexpected status reason", "SAMLV2.0 Assertion successfuly validated", status.getReason());
+
+ // now let's temper the first SAML assertion and try to validate them all again.
+ assertion1.getFirstChild().getFirstChild().setNodeValue("Tempered Issuer");
+ request1.getValidateTarget().setAny(assertion1);
+ request2.getValidateTarget().setAny(assertion2);
+ responseMessage = this.tokenService.invoke(factory.marshallRequestSecurityTokenCollection(collection));
+
+ baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ responseCollection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 2, responseCollection.getRequestSecurityTokenResponses().size());
+
+ // this time the first assertion should fail the digital signature verification.
+ response = responseCollection.getRequestSecurityTokenResponses().get(0);
+ assertEquals("Unexpected response context", "validatecontext1", response.getContext());
+ assertEquals("Unexpected token type", WSTrustConstants.STATUS_TYPE, response.getTokenType().toString());
+ status = response.getStatus();
+ assertNotNull("Unexpected null status", status);
+ assertEquals("Unexpected status code", WSTrustConstants.STATUS_CODE_INVALID, status.getCode());
+ assertEquals("Unexpected status reason", "Validation failure: digital signature is invalid", status.getReason());
+
+ response = responseCollection.getRequestSecurityTokenResponses().get(1);
+ assertEquals("Unexpected response context", "validatecontext2", response.getContext());
+ assertEquals("Unexpected token type", WSTrustConstants.STATUS_TYPE, response.getTokenType().toString());
+ status = response.getStatus();
+ assertNotNull("Unexpected null status", status);
+ assertEquals("Unexpected status code", WSTrustConstants.STATUS_CODE_VALID, status.getCode());
+ assertEquals("Unexpected status reason", "SAMLV2.0 Assertion successfuly validated", status.getReason());
+ }
+
+ /**
+ * <p>
+ * This test sends a {@code BatchRenew} request to the STS in an attempt to renew two different security tokens using
+ * a single WS-Trust request message.
+ * </p>
+ *
+ * @throws Exception if an error occurs while running the test.
+ */
+ public void testBatchRenew() throws Exception
+ {
+ // first issue two assertions, one using the token type and the other using applies to.
+ RequestSecurityToken request1 = this.createRequest("context1", WSTrustConstants.BATCH_ISSUE_REQUEST,
+ SAMLUtil.SAML2_TOKEN_TYPE, null);
+ RequestSecurityToken request2 = this.createRequest("context2", WSTrustConstants.BATCH_ISSUE_REQUEST, null,
+ "http://services.testcorp.org/provider2");
+
+ // create a request collection that includes the two issue requests.
+ RequestSecurityTokenCollection collection = new RequestSecurityTokenCollection();
+ collection.addRequestSecurityToken(request1);
+ collection.addRequestSecurityToken(request2);
+
+ // use the factory to marshal the request collection.
+ WSTrustJAXBFactory factory = WSTrustJAXBFactory.getInstance();
+ Source requestMessage = factory.marshallRequestSecurityTokenCollection(collection);
+
+ // invoke the token service.
+ Source responseMessage = this.tokenService.invoke(requestMessage);
+
+ // validate the response and get the SAML assertions from the request.
+ BaseRequestSecurityTokenResponse baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection responseCollection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 2, responseCollection.getRequestSecurityTokenResponses().size());
+
+ Element assertion1 = (Element) responseCollection.getRequestSecurityTokenResponses().get(0)
+ .getRequestedSecurityToken().getAny();
+ Element assertion2 = (Element) responseCollection.getRequestSecurityTokenResponses().get(1)
+ .getRequestedSecurityToken().getAny();
+
+ // now construct a WS-Trust batch validate request with the generated assertion.
+ request1 = this.createRequest("renewcontext1", WSTrustConstants.BATCH_RENEW_REQUEST,
+ WSTrustConstants.STATUS_TYPE, null);
+ RenewTargetType renewTarget1 = new RenewTargetType();
+ renewTarget1.setAny(assertion1);
+ request1.setRenewTarget(renewTarget1);
+
+ request2 = this.createRequest("renewcontext2", WSTrustConstants.BATCH_RENEW_REQUEST,
+ WSTrustConstants.STATUS_TYPE, null);
+ RenewTargetType renewTarget2 = new RenewTargetType();
+ renewTarget2.setAny(assertion2);
+ request2.setRenewTarget(renewTarget2);
+
+ collection = new RequestSecurityTokenCollection();
+ collection.addRequestSecurityToken(request1);
+ collection.addRequestSecurityToken(request2);
+
+ // invoke the token service.
+ responseMessage = this.tokenService.invoke(factory.marshallRequestSecurityTokenCollection(collection));
+ baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ responseCollection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 2, responseCollection.getRequestSecurityTokenResponses().size());
+
+ // extract the renewed assertions.
+ Element renewedAssertionElement1 = (Element) responseCollection.getRequestSecurityTokenResponses().get(0)
+ .getRequestedSecurityToken().getAny();
+ Element renewedAssertionElement2 = (Element) responseCollection.getRequestSecurityTokenResponses().get(1)
+ .getRequestedSecurityToken().getAny();
+
+ // check if both assertions have been renewed: lifetime must have been updated and ID must have been renewed.
+ AssertionType originalAssertion1 = SAMLUtil.fromElement(assertion1);
+ AssertionType originalAssertion2 = SAMLUtil.fromElement(assertion2);
+ AssertionType renewedAssertion1 = SAMLUtil.fromElement(renewedAssertionElement1);
+ AssertionType renewedAssertion2 = SAMLUtil.fromElement(renewedAssertionElement2);
+
+ // assertions should have different ids and lifetimes.
+ assertFalse("Renewed assertion should have a unique id", originalAssertion1.getID().equals(
+ renewedAssertion1.getID()));
+ assertFalse("Renewed assertion should have a unique id", originalAssertion2.getID().equals(
+ renewedAssertion2.getID()));
+ assertEquals(DatatypeConstants.LESSER, originalAssertion1.getConditions().getNotBefore().compare(
+ renewedAssertion1.getConditions().getNotBefore()));
+ assertEquals(DatatypeConstants.LESSER, originalAssertion1.getConditions().getNotOnOrAfter().compare(
+ renewedAssertion1.getConditions().getNotOnOrAfter()));
+ assertEquals(DatatypeConstants.LESSER, originalAssertion2.getConditions().getNotBefore().compare(
+ renewedAssertion2.getConditions().getNotBefore()));
+ assertEquals(DatatypeConstants.LESSER, originalAssertion2.getConditions().getNotOnOrAfter().compare(
+ renewedAssertion2.getConditions().getNotOnOrAfter()));
+ }
+
+ /**
+ * <p>
+ * This test sends a {@code BatchCancel} request to the STS in an attempt to cancel three different security tokens
+ * using a single WS-Trust request message.
+ * </p>
+ *
+ * @throws Exception if an error occurs while running the test.
+ */
+ public void testBatchCancel() throws Exception
+ {
+ // first issue three assertions, two using the token type and one using applies to.
+ RequestSecurityToken request1 = this.createRequest("context1", WSTrustConstants.BATCH_ISSUE_REQUEST,
+ SAMLUtil.SAML2_TOKEN_TYPE, null);
+ RequestSecurityToken request2 = this.createRequest("context2", WSTrustConstants.BATCH_ISSUE_REQUEST,
+ SAMLUtil.SAML2_TOKEN_TYPE, null);
+ RequestSecurityToken request3 = this.createRequest("context3", WSTrustConstants.BATCH_ISSUE_REQUEST, null,
+ "http://services.testcorp.org/provider2");
+
+ // create a request collection that includes the three issue requests.
+ RequestSecurityTokenCollection collection = new RequestSecurityTokenCollection();
+ collection.addRequestSecurityToken(request1);
+ collection.addRequestSecurityToken(request2);
+ collection.addRequestSecurityToken(request3);
+
+ // use the factory to marshal the request collection.
+ WSTrustJAXBFactory factory = WSTrustJAXBFactory.getInstance();
+ Source requestMessage = factory.marshallRequestSecurityTokenCollection(collection);
+
+ // invoke the token service.
+ Source responseMessage = this.tokenService.invoke(requestMessage);
+
+ // validate the response and get the SAML assertions from the request.
+ BaseRequestSecurityTokenResponse baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ RequestSecurityTokenResponseCollection responseCollection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 3, responseCollection.getRequestSecurityTokenResponses().size());
+
+ Element assertion1 = (Element) responseCollection.getRequestSecurityTokenResponses().get(0)
+ .getRequestedSecurityToken().getAny();
+ Element assertion2 = (Element) responseCollection.getRequestSecurityTokenResponses().get(1)
+ .getRequestedSecurityToken().getAny();
+ Element assertion3 = (Element) responseCollection.getRequestSecurityTokenResponses().get(2)
+ .getRequestedSecurityToken().getAny();
+
+ // now cancel two of the three assertions using the BatchCancel request type.
+ request1 = this.createRequest("cancelcontext1", WSTrustConstants.BATCH_CANCEL_REQUEST,
+ WSTrustConstants.STATUS_TYPE, null);
+ CancelTargetType cancelTarget1 = new CancelTargetType();
+ cancelTarget1.setAny(assertion1);
+ request1.setCancelTarget(cancelTarget1);
+
+ request2 = this.createRequest("cancelcontext2", WSTrustConstants.BATCH_CANCEL_REQUEST,
+ WSTrustConstants.STATUS_TYPE, null);
+ CancelTargetType cancelTarget2 = new CancelTargetType();
+ cancelTarget2.setAny(assertion2);
+ request2.setCancelTarget(cancelTarget2);
+
+ collection = new RequestSecurityTokenCollection();
+ collection.addRequestSecurityToken(request1);
+ collection.addRequestSecurityToken(request2);
+
+ // invoke the token service.
+ responseMessage = this.tokenService.invoke(factory.marshallRequestSecurityTokenCollection(collection));
+ baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ responseCollection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 2, responseCollection.getRequestSecurityTokenResponses().size());
+
+ // validate the response message.
+ RequestSecurityTokenResponse response = responseCollection.getRequestSecurityTokenResponses().get(0);
+ assertEquals("Unexpected response context", "cancelcontext1", response.getContext());
+ assertNotNull("Cancel response should contain a RequestedTokenCancelled element", response
+ .getRequestedTokenCancelled());
+ response = responseCollection.getRequestSecurityTokenResponses().get(1);
+ assertEquals("Unexpected response context", "cancelcontext2", response.getContext());
+ assertNotNull("Cancel response should contain a RequestedTokenCancelled element", response
+ .getRequestedTokenCancelled());
+
+ // now let's validate all assertions using a batch validate request.
+ request1 = this.createRequest("validatecontext1", WSTrustConstants.BATCH_VALIDATE_REQUEST,
+ WSTrustConstants.STATUS_TYPE, null);
+ ValidateTargetType validateTarget1 = new ValidateTargetType();
+ validateTarget1.setAny(assertion1);
+ request1.setValidateTarget(validateTarget1);
+ request2 = this.createRequest("validatecontext2", WSTrustConstants.BATCH_VALIDATE_REQUEST,
+ WSTrustConstants.STATUS_TYPE, null);
+ ValidateTargetType validateTarget2 = new ValidateTargetType();
+ validateTarget2.setAny(assertion2);
+ request2.setValidateTarget(validateTarget2);
+ request3 = this.createRequest("validatecontext3", WSTrustConstants.BATCH_VALIDATE_REQUEST,
+ WSTrustConstants.STATUS_TYPE, null);
+ ValidateTargetType validateTarget3 = new ValidateTargetType();
+ validateTarget3.setAny(assertion3);
+ request3.setValidateTarget(validateTarget3);
+
+ collection = new RequestSecurityTokenCollection();
+ collection.addRequestSecurityToken(request1);
+ collection.addRequestSecurityToken(request2);
+ collection.addRequestSecurityToken(request3);
+
+ // invoke the token service.
+ responseMessage = this.tokenService.invoke(factory.marshallRequestSecurityTokenCollection(collection));
+ baseResponse = factory.parseRequestSecurityTokenResponse(responseMessage);
+ assertNotNull("Unexpected null response", baseResponse);
+ assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
+ responseCollection = (RequestSecurityTokenResponseCollection) baseResponse;
+ assertEquals("Unexpected number of responses", 3, responseCollection.getRequestSecurityTokenResponses().size());
+
+ // the first two assertions should have been considered invalid as they have been previously canceled.
+ response = responseCollection.getRequestSecurityTokenResponses().get(0);
+ assertEquals("Unexpected response context", "validatecontext1", response.getContext());
+ assertEquals("Unexpected token type", WSTrustConstants.STATUS_TYPE, response.getTokenType().toString());
+ StatusType status = response.getStatus();
+ assertNotNull("Unexpected null status", status);
+ assertEquals("Unexpected status code", WSTrustConstants.STATUS_CODE_INVALID, status.getCode());
+ assertEquals("Unexpected status reason", "Validation failure: assertion with id " + assertion1.getAttribute("ID")
+ + " has been canceled", status.getReason());
+
+ response = responseCollection.getRequestSecurityTokenResponses().get(1);
+ assertEquals("Unexpected response context", "validatecontext2", response.getContext());
+ assertEquals("Unexpected token type", WSTrustConstants.STATUS_TYPE, response.getTokenType().toString());
+ status = response.getStatus();
+ assertNotNull("Unexpected null status", status);
+ assertEquals("Unexpected status code", WSTrustConstants.STATUS_CODE_INVALID, status.getCode());
+ assertEquals("Unexpected status reason", "Validation failure: assertion with id " + assertion2.getAttribute("ID")
+ + " has been canceled", status.getReason());
+
+ // third assertion should be considered valid.
+ response = responseCollection.getRequestSecurityTokenResponses().get(2);
+ assertEquals("Unexpected response context", "validatecontext3", response.getContext());
+ assertEquals("Unexpected token type", WSTrustConstants.STATUS_TYPE, response.getTokenType().toString());
+ status = response.getStatus();
+ assertNotNull("Unexpected null status", status);
+ assertEquals("Unexpected status code", WSTrustConstants.STATUS_CODE_VALID, status.getCode());
+ assertEquals("Unexpected status reason", "SAMLV2.0 Assertion successfuly validated", status.getReason());
+
+ // now try to renew one of the canceled assertions.
+ request1 = this.createRequest("renewcontext", WSTrustConstants.RENEW_REQUEST, null, null);
+ RenewTargetType renewTarget = new RenewTargetType();
+ renewTarget.setAny(assertion1);
+ request1.setRenewTarget(renewTarget);
+
+ // we should receive an exception when renewing the token.
+ try
+ {
+ this.tokenService.invoke(factory.marshallRequestSecurityToken(request1));
+ fail("Renewing a canceled token should result in an exception being thrown");
+ }
+ catch (WebServiceException we)
+ {
+ assertTrue("Unexpected cause type", we.getCause() instanceof WSTrustException);
+ assertEquals("Unexpected exception message", "Assertion with id " + assertion1.getAttribute("ID")
+ + " has been canceled and cannot be renewed", we.getCause().getMessage());
+ }
+
+ }
+
+ /**
+ * <p>
* This test tries to request a token of an unknown type, checking if an exception is correctly thrown by the
* security token service.
* </p>
@@ -829,7 +1297,7 @@
RequestSecurityToken request = this.createRequest("testcontext", WSTrustConstants.ISSUE_REQUEST,
"http://www.tokens.org/UnknownToken", null);
- // use the factory to marshall the request.
+ // use the factory to marshal the request.
WSTrustJAXBFactory factory = WSTrustJAXBFactory.getInstance();
Source requestMessage = factory.marshallRequestSecurityToken(request);
@@ -1080,20 +1548,15 @@
* SpecialTokenProvider}.
* </p>
*
- * @param baseResponse a reference to the WS-Trust response that was sent by the STS.
+ * @param response a reference to the WS-Trust response that was sent by the STS.
+ * @param context a {@code String} representing the response context name.
* @throws Exception if one of the validation performed fail.
*/
- private void validateCustomTokenResponse(BaseRequestSecurityTokenResponse baseResponse) throws Exception
+ private void validateCustomTokenResponse(RequestSecurityTokenResponse response, String context) throws Exception
{
// =============================== WS-Trust Security Token Response Validation ===============================//
-
- assertNotNull("Unexpected null response", baseResponse);
- assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
- RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
- assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
- RequestSecurityTokenResponse response = collection.getRequestSecurityTokenResponses().get(0);
- assertEquals("Unexpected response context", "testcontext", response.getContext());
+ assertEquals("Unexpected response context", context, response.getContext());
assertEquals("Unexpected token type", "http://www.tokens.org/SpecialToken", response.getTokenType().toString());
Lifetime lifetime = response.getLifetime();
assertNotNull("Unexpected null token lifetime", lifetime);
@@ -1119,7 +1582,7 @@
* SAML20TokenProvider}.
* </p>
*
- * @param baseResponse a reference to the WS-Trust response that was sent by the STS.
+ * @param response a reference to the WS-Trust response that was sent by the STS.
* @param context the expected name of the response context.
* @param principal the principal that is expected to be seen in the assertion subject.
* @param confirmationMethod the confirmation method that is expected to be seen in the assertion subject.
@@ -1127,17 +1590,11 @@
* methods to perform extra validations depending on the scenario being tested.
* @throws Exception if an error occurs while performing the validation.
*/
- private AssertionType validateSAMLAssertionResponse(BaseRequestSecurityTokenResponse baseResponse, String context,
+ private AssertionType validateSAMLAssertionResponse(RequestSecurityTokenResponse response, String context,
String principal, String confirmationMethod) throws Exception
{
// =============================== WS-Trust Security Token Response Validation ===============================//
-
- assertNotNull("Unexpected null response", baseResponse);
- assertTrue("Unexpected response type", baseResponse instanceof RequestSecurityTokenResponseCollection);
- RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
- assertEquals("Unexpected number of responses", 1, collection.getRequestSecurityTokenResponses().size());
- RequestSecurityTokenResponse response = collection.getRequestSecurityTokenResponses().get(0);
assertEquals("Unexpected response context", context, response.getContext());
assertEquals("Unexpected token type", SAMLUtil.SAML2_TOKEN_TYPE, response.getTokenType().toString());
Lifetime lifetime = response.getLifetime();
More information about the picketlink-commits
mailing list