Author: sguilhen(a)redhat.com
Date: 2009-09-23 19:08:09 -0400 (Wed, 23 Sep 2009)
New Revision: 807
Added:
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/endorsed/
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/endorsed/serializer.jar
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/endorsed/xalan.jar
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/keystore/
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/keystore/sts_keystore.jks
Modified:
identity-federation/trunk/jboss-identity-bindings/src/test/java/org/jboss/test/identity/federation/bindings/wstrust/JBossSTSUnitTestCase.java
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/saml/v2/factories/SAMLAssertionFactory.java
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/StandardRequestHandler.java
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/WSTrustRequestContext.java
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/WSTrustUtil.java
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAML20TokenProvider.java
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAMLUtil.java
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java
identity-federation/trunk/jboss-identity-fed-core/src/test/java/org/jboss/test/identity/federation/core/wstrust/SAML20TokenProviderUnitTestCase.java
Log:
JBID-138: StandardRequestHandler now sets the proof token in a KeyInfoType object and then
sets this KeyInfoType in the request context. SAML20TokenProvider gets the KeyInfo from
the context and sets it in the SubjectConfirmation, as required by the SAML token profile.
Tests have been updated.
Modified:
identity-federation/trunk/jboss-identity-bindings/src/test/java/org/jboss/test/identity/federation/bindings/wstrust/JBossSTSUnitTestCase.java
===================================================================
---
identity-federation/trunk/jboss-identity-bindings/src/test/java/org/jboss/test/identity/federation/bindings/wstrust/JBossSTSUnitTestCase.java 2009-09-23
08:31:30 UTC (rev 806)
+++
identity-federation/trunk/jboss-identity-bindings/src/test/java/org/jboss/test/identity/federation/bindings/wstrust/JBossSTSUnitTestCase.java 2009-09-23
23:08:09 UTC (rev 807)
@@ -294,7 +294,7 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- this.validateSAMLAssertionResponse(baseResponse);
+ this.validateSAMLAssertionResponse(baseResponse, SAMLUtil.SAML2_BEARER_URI);
}
/**
@@ -351,7 +351,7 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse);
+ AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse,
SAMLUtil.SAML2_BEARER_URI);
// in this scenario, the conditions section should have an audience restriction.
ConditionsType conditions = assertion.getConditions();
@@ -379,7 +379,7 @@
public void testInvokeSAML20WithProofToken() throws Exception
{
// create a simple token request, asking for a SAMLv2.0 token.
- RequestSecurityToken request = this.createRequest("testcontext",
WSTrustConstants.ISSUE_REQUEST,
+ RequestSecurityToken request = this.createRequest("testcontext",
WSTrustConstants.ISSUE_REQUEST,
SAMLUtil.SAML2_TOKEN_TYPE, null);
// add a symmetric key type to the request, but don't supply any client key -
STS should generate one.
@@ -395,7 +395,7 @@
.parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- this.validateSAMLAssertionResponse(baseResponse);
+ this.validateSAMLAssertionResponse(baseResponse, SAMLUtil.SAML2_BEARER_URI);
// check if the response contains the STS-generated key.
RequestSecurityTokenResponseCollection collection =
(RequestSecurityTokenResponseCollection) baseResponse;
@@ -427,7 +427,7 @@
baseResponse =
WSTrustJAXBFactory.getInstance().parseRequestSecurityTokenResponse(responseMessage);
// validate the security token response.
- this.validateSAMLAssertionResponse(baseResponse);
+ this.validateSAMLAssertionResponse(baseResponse, SAMLUtil.SAML2_BEARER_URI);
collection = (RequestSecurityTokenResponseCollection) baseResponse;
response = collection.getRequestSecurityTokenResponses().get(0);
@@ -607,7 +607,8 @@
* @throws Exception
* if one of the validation performed fail.
*/
- private AssertionType validateSAMLAssertionResponse(BaseRequestSecurityTokenResponse
baseResponse) throws Exception
+ private AssertionType validateSAMLAssertionResponse(BaseRequestSecurityTokenResponse
baseResponse,
+ String confirmationMethod) throws Exception
{
// =============================== WS-Trust Security Token Response Validation
===============================//
@@ -667,8 +668,14 @@
assertEquals("Unexpected name id value", "sguilhen",
nameID.getValue());
assertEquals("Unexpected type found", SubjectConfirmationType.class,
content.get(1).getDeclaredType());
SubjectConfirmationType subjType = (SubjectConfirmationType)
content.get(1).getValue();
- assertEquals("Unexpected confirmation method", SAMLUtil.SAML2_BEARER_URI,
subjType.getMethod());
+ assertEquals("Unexpected confirmation method", confirmationMethod,
subjType.getMethod());
+ // if confirmation method is holder of key, make sure the assertion contains a
KeyInfo with the proof token.
+ if(SAMLUtil.SAML2_HOLDER_OF_KEY_URI.equals(confirmationMethod))
+ {
+
+ }
+
// validate the assertion conditions.
assertNotNull("Unexpected null conditions", assertion.getConditions());
assertEquals(lifetime.getCreated(), assertion.getConditions().getNotBefore());
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/saml/v2/factories/SAMLAssertionFactory.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/saml/v2/factories/SAMLAssertionFactory.java 2009-09-23
08:31:30 UTC (rev 806)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/saml/v2/factories/SAMLAssertionFactory.java 2009-09-23
23:08:09 UTC (rev 807)
@@ -37,6 +37,7 @@
import org.jboss.identity.federation.saml.v2.assertion.StatementAbstractType;
import org.jboss.identity.federation.saml.v2.assertion.SubjectConfirmationType;
import org.jboss.identity.federation.saml.v2.assertion.SubjectType;
+import org.jboss.identity.xmlsec.w3.xmldsig.KeyInfoType;
/**
* Get the SAML Assertion Object Factory
@@ -111,6 +112,21 @@
/**
* <p>
+ * Creates a {@code KeyInfoConfirmationDataType} with the specified {@code
KeyInfoType}.
+ * </p>
+ *
+ * @param keyInfo the {@code KeyInfoType} object that wraps the proof-of-possession
token.
+ * @return the constructed {@code KeyInfoConfirmationDataType} instance.
+ */
+ public static KeyInfoConfirmationDataType createKeyInfoConfirmation(KeyInfoType
keyInfo)
+ {
+ KeyInfoConfirmationDataType type =
getObjectFactory().createKeyInfoConfirmationDataType();
+ type.getContent().add(new
org.jboss.identity.xmlsec.w3.xmldsig.ObjectFactory().createKeyInfo(keyInfo));
+ return type;
+ }
+
+ /**
+ * <p>
* Creates a {@code SubjectConfirmationType} object with the specified values.
* </p>
*
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/StandardRequestHandler.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/StandardRequestHandler.java 2009-09-23
08:31:30 UTC (rev 806)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/StandardRequestHandler.java 2009-09-23
23:08:09 UTC (rev 807)
@@ -22,13 +22,11 @@
package org.jboss.identity.federation.core.wstrust;
import java.net.URI;
-import java.security.InvalidKeyException;
import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PublicKey;
+import java.security.cert.Certificate;
-import javax.xml.bind.JAXBElement;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.SignatureMethod;
@@ -141,6 +139,9 @@
keySize = KEY_SIZE;
request.setKeySize(keySize);
}
+
+ // get the key wrap algorithm.
+ URI keyWrapAlgo = request.getKeyWrapAlgorithm();
// create proof-of-possession token and server entropy (if needed).
RequestedProofTokenType requestedProofToken = null;
@@ -148,9 +149,10 @@
if (WSTrustConstants.KEY_TYPE_SYMMETRIC.equalsIgnoreCase(keyType.toString()))
{
+ // symmetric key case: if client entropy is found, compute a key. If not,
generate a new key.
requestedProofToken = new RequestedProofTokenType();
ObjectFactory objFactory = new ObjectFactory();
- // symmetric key case: if client entropy is found, compute a key. If not,
generate a new key.
+
byte[] clientSecret = null;
EntropyType clientEntropy = request.getEntropy();
if (clientEntropy != null)
@@ -167,26 +169,32 @@
{
// client secret has been specified - combine it with the sts secret.
requestedProofToken.setAny(objFactory.createComputedKey(WSTrustConstants.CK_PSHA1));
+ byte[] combinedSecret = null;
try
{
- byte[] combinedSecret = WSTrustUtil.P_SHA1(clientSecret, serverSecret,
(int) keySize / 8);
- requestContext.setProofToken(combinedSecret);
+ combinedSecret = WSTrustUtil.P_SHA1(clientSecret, serverSecret, (int)
keySize / 8);
}
catch (Exception e)
{
throw new WSTrustException("Error generating combined secret
key", e);
}
+ requestContext.setProofTokenInfo(WSTrustUtil.createKeyInfo(combinedSecret,
providerPublicKey, keyWrapAlgo));
}
else
{
// client secret has not been specified - use the sts secret only.
requestedProofToken.setAny(objFactory.createBinarySecret(serverBinarySecret));
- requestContext.setProofToken(serverSecret);
+ requestContext.setProofTokenInfo(WSTrustUtil.createKeyInfo(serverSecret,
providerPublicKey, keyWrapAlgo));
}
}
else if (WSTrustConstants.KEY_TYPE_PUBLIC.equalsIgnoreCase(keyType.toString()))
{
- // TODO: implement public key case.
+ // TODO: get the client certificate from a metadata provider or from the
UseKey section of the WS-T request.
+ Certificate certificate = null;
+ if(certificate != null)
+ requestContext.setProofTokenInfo(WSTrustUtil.createKeyInfo(certificate));
+ else
+ throw new WSTrustException("Unable to locate client public
key");
}
// issue the security token using the constructed context.
@@ -458,4 +466,5 @@
return rstrDocument;
}
+
}
\ No newline at end of file
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/WSTrustRequestContext.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/WSTrustRequestContext.java 2009-09-23
08:31:30 UTC (rev 806)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/WSTrustRequestContext.java 2009-09-23
23:08:09 UTC (rev 807)
@@ -27,6 +27,7 @@
import org.jboss.identity.federation.core.wstrust.wrappers.RequestSecurityToken;
import org.jboss.identity.federation.ws.trust.RequestedReferenceType;
import org.jboss.identity.federation.ws.trust.StatusType;
+import org.jboss.identity.xmlsec.w3.xmldsig.KeyInfoType;
/**
* <p>
@@ -49,7 +50,7 @@
private final RequestSecurityToken request;
- private Object proofToken;
+ private KeyInfoType proofTokenInfo;
// information supplied by the token provider.
private SecurityToken securityToken;
@@ -149,26 +150,26 @@
/**
* <p>
- * Obtains the proof-of-possession token.
+ * Obtains the {@code KeyInfoType} that contains the proof-of-possession token.
* </p>
*
- * @return an {@code Object} representing the proof-of-possession token.
+ * @return a reference to the {@code KeyInfoType} that wraps the proof-of-possession
token.
*/
- public Object getProofToken()
+ public KeyInfoType getProofTokenInfo()
{
- return this.proofToken;
+ return this.proofTokenInfo;
}
/**
* <p>
- * Sets the proof-of-possession token in the request context.
+ * Sets the {@code KeyInfoType} that contains the proof-of-possession token.
* </p>
*
- * @param proofToken an {@code Object} representing the proof-of-possession token.
+ * @param proofTokenInfo a reference to the {@code KeyInfoType} that wraps the
proof-of-possession token.
*/
- public void setProofToken(Object proofToken)
+ public void setProofTokenInfo(KeyInfoType proofTokenInfo)
{
- this.proofToken = proofToken;
+ this.proofTokenInfo = proofTokenInfo;
}
/**
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/WSTrustUtil.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/WSTrustUtil.java 2009-09-23
08:31:30 UTC (rev 806)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/WSTrustUtil.java 2009-09-23
23:08:09 UTC (rev 807)
@@ -21,9 +21,12 @@
*/
package org.jboss.identity.federation.core.wstrust;
+import java.net.URI;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
import java.security.SecureRandom;
+import java.security.cert.Certificate;
import java.util.GregorianCalendar;
import java.util.Map;
@@ -32,6 +35,10 @@
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
+import org.apache.xml.security.encryption.EncryptedKey;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.jboss.identity.federation.core.saml.v2.util.DocumentUtil;
+import org.jboss.identity.federation.core.util.XMLEncryptionUtil;
import org.jboss.identity.federation.core.wstrust.wrappers.Lifetime;
import org.jboss.identity.federation.ws.addressing.AttributedURIType;
import org.jboss.identity.federation.ws.addressing.EndpointReferenceType;
@@ -42,6 +49,10 @@
import org.jboss.identity.federation.ws.trust.RequestedReferenceType;
import org.jboss.identity.federation.ws.wss.secext.KeyIdentifierType;
import org.jboss.identity.federation.ws.wss.secext.SecurityTokenReferenceType;
+import org.jboss.identity.xmlsec.w3.xmldsig.KeyInfoType;
+import org.jboss.identity.xmlsec.w3.xmldsig.X509DataType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
/**
* <p>
@@ -202,7 +213,7 @@
random.nextBytes(secret);
return secret;
}
-
+
/**
* <p>
* This method implements the {@code P_SHA-1} function as defined in the <i>RFC
2246 - The TLS Protocol Version 1.0
@@ -263,4 +274,79 @@
return result;
}
+ /**
+ * <p>
+ * Creates a {@code KeyInfoType} that wraps the specified secret. If the {@code
encryptionKey} parameter is not
+ * null, the secret is encrypted using the specified public key before it is set in
the {@code KeyInfoType}.
+ * </p>
+ *
+ * @param secret a {@code byte[]} representing the secret (symmetric key).
+ * @param encryptionKey the {@code PublicKey} that must be used to encrypt the
secret.
+ * @param keyWrapAlgo the key wrap algorithm to be used.
+ * @return the constructed {@code KeyInfoType} instance.
+ * @throws WSTrustException if an error occurs while creating the {@code KeyInfoType}
object.
+ */
+ public static KeyInfoType createKeyInfo(byte[] secret, PublicKey encryptionKey, URI
keyWrapAlgo)
+ throws WSTrustException
+ {
+ KeyInfoType keyInfo = null;
+
+ // if a public key has been specified, encrypt the secret using the public key.
+ if (encryptionKey != null)
+ {
+ try
+ {
+ Document document = DocumentUtil.createDocument();
+ // TODO: XMLEncryptionUtil should allow for the specification of the key wrap
algorithm.
+ EncryptedKey key = XMLEncryptionUtil.encryptKey(document, new
SecretKeySpec(secret, "AES"), encryptionKey,
+ secret.length);
+ Element encryptedKeyElement = XMLCipher.getInstance().martial(key);
+ keyInfo = new KeyInfoType();
+ keyInfo.getContent().add(encryptedKeyElement);
+ }
+ catch (Exception e)
+ {
+ throw new WSTrustException("Error creating KeyInfoType", e);
+ }
+ }
+ else
+ {
+ // TODO: log a warn message or throw an exception to inform client that the
secret could not be encrypted.
+ }
+ return keyInfo;
+ }
+
+ /**
+ * <p>
+ * Creates a {@code KeyInfoType} that wraps the specified certificate.
+ * </p>
+ *
+ * @param certificate the {@code Certificate} to be wrapped as a {@code X509DataType}
inside the {@code KeyInfoType}.
+ * @return the constructed {@code KeyInfoType} object.
+ * @throws WSTrustException if an error occurs while creating the {@code
KeyInfoType}.
+ */
+ public static KeyInfoType createKeyInfo(Certificate certificate) throws
WSTrustException
+ {
+ KeyInfoType keyInfo = null;
+ try
+ {
+ // TODO: check if we need to store the certificate using a base64 format.
+ byte[] encodedCert = certificate.getEncoded();
+
+ // first create a X509DataType that contains the encoded certificate.
+ org.jboss.identity.xmlsec.w3.xmldsig.ObjectFactory factory = new
org.jboss.identity.xmlsec.w3.xmldsig.ObjectFactory();
+ X509DataType dataType = factory.createX509DataType();
+ dataType.getX509IssuerSerialOrX509SKIOrX509SubjectName().add(
+ factory.createX509DataTypeX509Certificate(encodedCert));
+
+ // set the X509DataType in the KeyInfoType.
+ keyInfo = new KeyInfoType();
+ keyInfo.getContent().add(factory.createX509Data(dataType));
+ }
+ catch (Exception e)
+ {
+ throw new WSTrustException("Error creating KeyInfoType", e);
+ }
+ return keyInfo;
+ }
}
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAML20TokenProvider.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAML20TokenProvider.java 2009-09-23
08:31:30 UTC (rev 806)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAML20TokenProvider.java 2009-09-23
23:08:09 UTC (rev 807)
@@ -43,6 +43,7 @@
import org.jboss.identity.federation.saml.v2.assertion.AssertionType;
import org.jboss.identity.federation.saml.v2.assertion.AudienceRestrictionType;
import org.jboss.identity.federation.saml.v2.assertion.ConditionsType;
+import org.jboss.identity.federation.saml.v2.assertion.KeyInfoConfirmationDataType;
import org.jboss.identity.federation.saml.v2.assertion.NameIDType;
import org.jboss.identity.federation.saml.v2.assertion.SubjectConfirmationType;
import org.jboss.identity.federation.saml.v2.assertion.SubjectType;
@@ -211,10 +212,20 @@
ConditionsType conditions =
SAMLAssertionFactory.createConditions(lifetime.getCreated(), lifetime.getExpires(),
restriction);
- // TODO: implement support for the other confirmation methods.
- String confirmationMethod = SAMLUtil.SAML2_BEARER_URI;
+ String confirmationMethod = null;
+ KeyInfoConfirmationDataType keyInfoDataType = null;
+ // if there is a proof-of-possession token in the context, we have the holder of
key confirmation method.
+ if (context.getProofTokenInfo() != null)
+ {
+ confirmationMethod = SAMLUtil.SAML2_HOLDER_OF_KEY_URI;
+ keyInfoDataType =
SAMLAssertionFactory.createKeyInfoConfirmation(context.getProofTokenInfo());
+ }
+ else
+ confirmationMethod = SAMLUtil.SAML2_BEARER_URI;
+ // TODO: implement the SENDER_VOUCHES scenario.
+
SubjectConfirmationType subjectConfirmation =
SAMLAssertionFactory.createSubjectConfirmation(null,
- confirmationMethod, null);
+ confirmationMethod, keyInfoDataType);
// create a subject using the caller principal.
Principal principal = context.getCallerPrincipal();
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAMLUtil.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAMLUtil.java 2009-09-23
08:31:30 UTC (rev 806)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAMLUtil.java 2009-09-23
23:08:09 UTC (rev 807)
@@ -47,6 +47,10 @@
public static final String SAML2_BEARER_URI =
"urn:oasis:names:tc:SAML:2.0:cm:bearer";
+ public static final String SAML2_HOLDER_OF_KEY_URI =
"urn:oasis:names:tc:SAML:2.0:cm:holder-of-key";
+
+ public static final String SAML2_SENDER_VOUCHES_URI =
"urn:oasis:names:tc:SAML:2.0:cm:sender-vouches";
+
public static final String SAML2_TOKEN_TYPE =
"http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0";
public static final String SAML2_VALUE_TYPE =
"http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID";
@@ -70,11 +74,11 @@
marshaller.marshal(new ObjectFactory().createAssertion(assertion), result);
// normalize the document to remove unused namespaces.
- DOMConfiguration docConfig = document.getDomConfig();
- docConfig.setParameter("namespaces", Boolean.TRUE);
- docConfig.setParameter("namespace-declarations", Boolean.FALSE);
- document.normalizeDocument();
-
+ // DOMConfiguration docConfig = document.getDomConfig();
+ // docConfig.setParameter("namespaces", Boolean.TRUE);
+ // docConfig.setParameter("namespace-declarations", Boolean.FALSE);
+ // document.normalizeDocument();
+
return document.getDocumentElement();
}
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java 2009-09-23
08:31:30 UTC (rev 806)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java 2009-09-23
23:08:09 UTC (rev 807)
@@ -135,6 +135,8 @@
private URI canonicalizationAlgorithm;
+ private URI keyWrapAlgorithm;
+
private ProofEncryptionType proofEncryption;
private UseKeyType useKey;
@@ -236,6 +238,8 @@
this.encryptionAlgorithm = URI.create((String) element.getValue());
else if (localName.equalsIgnoreCase("CanonicalizationAlgorithm"))
this.canonicalizationAlgorithm = URI.create((String) element.getValue());
+ else if (localName.equalsIgnoreCase("KeyWrapAlgorithm"))
+ this.keyWrapAlgorithm = URI.create((String) element.getValue());
else if (localName.equalsIgnoreCase("ProofEncryption"))
this.proofEncryption = (ProofEncryptionType) element.getValue();
else if (localName.equalsIgnoreCase("UseKey"))
@@ -716,6 +720,30 @@
/**
* <p>
+ * Obtains the key wrap algorithm that has been set in the request.
+ * </p>
+ *
+ * @return a {@code URI} that represents the key wrap algorithm.
+ */
+ public URI getKeyWrapAlgorithm()
+ {
+ return this.keyWrapAlgorithm;
+ }
+
+ /**
+ * <p>
+ * Sets the key wrap algorithm in the request.
+ * </p>
+ *
+ * @param keyWrapAlgorithm a {@code URI} that represents the algorithm to be set.
+ */
+ public void setKeyWrapAlgorithm(URI keyWrapAlgorithm)
+ {
+ this.keyWrapAlgorithm = keyWrapAlgorithm;
+ }
+
+ /**
+ * <p>
* Obtains the {@code ProofEncryption} section of the request. The {@code
ProofEncryption} indicates that the
* requester desires any returned secrets in issued security tokens to be encrypted.
* </p>
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/test/java/org/jboss/test/identity/federation/core/wstrust/SAML20TokenProviderUnitTestCase.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/test/java/org/jboss/test/identity/federation/core/wstrust/SAML20TokenProviderUnitTestCase.java 2009-09-23
08:31:30 UTC (rev 806)
+++
identity-federation/trunk/jboss-identity-fed-core/src/test/java/org/jboss/test/identity/federation/core/wstrust/SAML20TokenProviderUnitTestCase.java 2009-09-23
23:08:09 UTC (rev 807)
@@ -21,9 +21,15 @@
*/
package org.jboss.test.identity.federation.core.wstrust;
+import java.io.InputStream;
import java.net.URI;
+import java.security.KeyStore;
import java.security.Principal;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.util.Arrays;
import java.util.GregorianCalendar;
+import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
@@ -51,6 +57,9 @@
import org.jboss.identity.federation.ws.trust.ValidateTargetType;
import org.jboss.identity.federation.ws.wss.secext.KeyIdentifierType;
import org.jboss.identity.federation.ws.wss.secext.SecurityTokenReferenceType;
+import org.jboss.identity.xmlsec.w3.xmldsig.KeyInfoType;
+import org.jboss.identity.xmlsec.w3.xmldsig.X509DataType;
+import org.jboss.identity.xmlsec.w3.xmlenc.EncryptedKeyType;
import org.w3c.dom.Element;
/**
@@ -144,6 +153,96 @@
/**
* <p>
+ * This method tests the creation of SAMLV.20 assertions that contain a
proof-of-possession token - that is,
+ * assertions that use the Holder Of Key confirmation method.
+ * </p>
+ *
+ * @throws Exception if an error occurs while running the test.
+ */
+ public void testIssueSAMLV20HolderOfKeyToken() throws Exception
+ {
+ // create a WSTrustRequestContext with a simple WS-Trust request.
+ RequestSecurityToken request = new RequestSecurityToken();
+ request.setLifetime(WSTrustUtil.createDefaultLifetime(3600000));
+
request.setAppliesTo(WSTrustUtil.createAppliesTo("http://services.te...;
+ request.setTokenType(URI.create(SAMLUtil.SAML2_TOKEN_TYPE));
+
+ WSTrustRequestContext context = new WSTrustRequestContext(request, new
TestPrincipal("sguilhen"));
+ context.setTokenIssuer("JBossSTS");
+
+ // let's set a symmetric key proof-of-possession token in the context.
+ byte[] secret = WSTrustUtil.createRandomSecret(32);
+ PublicKey serviceKey = this.getCertificate("keystore/sts_keystore.jks",
"testpass", "service2").getPublicKey();
+ context.setProofTokenInfo(WSTrustUtil.createKeyInfo(secret, serviceKey, null));
+
+ // call the SAML token provider and check the generated token.
+ new SAML20TokenProvider().issueToken(context);
+ assertNotNull("Unexpected null security token",
context.getSecurityToken());
+
+ // check if the assertion has a subject confirmation that contains the encrypted
symmetric key.
+ AssertionType assertion = SAMLUtil.fromElement((Element)
context.getSecurityToken().getTokenValue());
+ SubjectType subject = assertion.getSubject();
+ assertNotNull("Unexpected null subject", subject);
+ assertEquals("Unexpected subject content size", 2,
subject.getContent().size());
+ JAXBElement<?> content = subject.getContent().get(0);
+ assertEquals("Unexpected content type", NameIDType.class,
content.getDeclaredType());
+ NameIDType nameID = (NameIDType) content.getValue();
+ assertEquals("Unexpected name id qualifier",
"urn:jboss:identity-federation", nameID.getNameQualifier());
+ assertEquals("Unexpected name id", "sguilhen",
nameID.getValue());
+ content = subject.getContent().get(1);
+ assertEquals("Unexpected content type", SubjectConfirmationType.class,
content.getDeclaredType());
+ SubjectConfirmationType confirmation = (SubjectConfirmationType)
content.getValue();
+ assertEquals("Unexpected confirmation method",
SAMLUtil.SAML2_HOLDER_OF_KEY_URI, confirmation.getMethod());
+ List<Object> confirmationContent =
confirmation.getSubjectConfirmationData().getContent();
+ assertEquals("Unexpected subject confirmation content size", 1,
confirmationContent.size());
+ JAXBElement<?> keyInfoElement = (JAXBElement<?>)
confirmationContent.get(0);
+ assertEquals("Unexpected subject confirmation context type",
KeyInfoType.class, keyInfoElement.getDeclaredType());
+ KeyInfoType keyInfo = (KeyInfoType) keyInfoElement.getValue();
+ assertEquals("Unexpected key info content size", 1,
keyInfo.getContent().size());
+ JAXBElement<?> encKeyElement = (JAXBElement<?>)
keyInfo.getContent().get(0);
+ assertEquals("Unexpected key info content type", EncryptedKeyType.class,
encKeyElement.getDeclaredType());
+
+ // Now let's set an asymmetric proof of possession token in the context.
+ Certificate certificate =
this.getCertificate("keystore/sts_keystore.jks", "testpass",
"service1");
+ context.setProofTokenInfo(WSTrustUtil.createKeyInfo(certificate));
+
+ // call the SAML token provider and check the generated token.
+ new SAML20TokenProvider().issueToken(context);
+ assertNotNull("Unexpected null security token",
context.getSecurityToken());
+
+ // check if the assertion has a subject confirmation that contains the encoded
certificate.
+ assertion = SAMLUtil.fromElement((Element)
context.getSecurityToken().getTokenValue());
+ subject = assertion.getSubject();
+ content = subject.getContent().get(0);
+ assertEquals("Unexpected content type", NameIDType.class,
content.getDeclaredType());
+ nameID = (NameIDType) content.getValue();
+ assertEquals("Unexpected name id qualifier",
"urn:jboss:identity-federation", nameID.getNameQualifier());
+ assertEquals("Unexpected name id", "sguilhen",
nameID.getValue());
+ content = subject.getContent().get(1);
+ assertEquals("Unexpected content type", SubjectConfirmationType.class,
content.getDeclaredType());
+ confirmation = (SubjectConfirmationType) content.getValue();
+ assertEquals("Unexpected confirmation method",
SAMLUtil.SAML2_HOLDER_OF_KEY_URI, confirmation.getMethod());
+ confirmationContent = confirmation.getSubjectConfirmationData().getContent();
+ assertEquals("Unexpected subject confirmation content size", 1,
confirmationContent.size());
+ keyInfoElement = (JAXBElement<?>) confirmationContent.get(0);
+ assertEquals("Unexpected subject confirmation context type",
KeyInfoType.class, keyInfoElement.getDeclaredType());
+ keyInfo = (KeyInfoType) keyInfoElement.getValue();
+ assertEquals("Unexpected key info content size", 1,
keyInfo.getContent().size());
+
+ // key info should contain a X509Data section with the encoded certificate.
+ JAXBElement<?> x509DataElement = (JAXBElement<?>)
keyInfo.getContent().get(0);
+ assertEquals("Unexpected key info content type", X509DataType.class,
x509DataElement.getDeclaredType());
+ X509DataType x509Data = (X509DataType) x509DataElement.getValue();
+ assertEquals("Unexpected X509 data content size", 1,
x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName().
+ size());
+ JAXBElement<?> x509CertElement = (JAXBElement<?>)
x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName().get(0);
+ assertEquals("Unexpected X509 data content type", byte[].class,
x509CertElement.getDeclaredType());
+ byte[] encodedCert = (byte[]) x509CertElement.getValue();
+ assertTrue("Invalid encoded certificate found",
Arrays.equals(certificate.getEncoded(), encodedCert));
+ }
+
+ /**
+ * <p>
* Tests the validation of a SAMLV2.0 Assertion.
* </p>
*
@@ -241,6 +340,27 @@
/**
* <p>
+ * Obtains the {@code Certificate} stored under the specified alias in the specified
keystore.
+ * </p>
+ *
+ * @param keyStoreFile the name of the file that contains a JKS keystore.
+ * @param passwd the keystore password.
+ * @param certificateAlias the alias of a certificate in the keystore.
+ * @return a reference to the {@code Certificate} stored under the given alias.
+ * @throws Exception if an error occurs while handling the keystore.
+ */
+ private Certificate getCertificate(String keyStoreFile, String passwd, String
certificateAlias) throws Exception
+ {
+ InputStream stream =
Thread.currentThread().getContextClassLoader().getResourceAsStream(keyStoreFile);
+ KeyStore keyStore = KeyStore.getInstance("JKS");
+ keyStore.load(stream, passwd.toCharArray());
+
+ Certificate certificate = keyStore.getCertificate(certificateAlias);
+ return certificate;
+ }
+
+ /**
+ * <p>
* Simple {@code Principal} implementation used in the test scenarios.
* </p>
*
Added:
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/endorsed/serializer.jar
===================================================================
(Binary files differ)
Property changes on:
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/endorsed/serializer.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added:
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/endorsed/xalan.jar
===================================================================
(Binary files differ)
Property changes on:
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/endorsed/xalan.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added:
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/keystore/sts_keystore.jks
===================================================================
(Binary files differ)
Property changes on:
identity-federation/trunk/jboss-identity-fed-core/src/test/resources/keystore/sts_keystore.jks
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream