Author: anil.saldhana(a)jboss.com
Date: 2011-02-17 21:28:51 -0500 (Thu, 17 Feb 2011)
New Revision: 753
Added:
federation/trunk/picketlink-web/src/test/java/org/picketlink/test/identity/federation/web/saml/handlers/SAML2AuthenticationHandlerUnitTestCase.java
Modified:
federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/bindings/tomcat/idp/IDPWebBrowserSSOValve.java
federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/bindings/tomcat/sp/SPRedirectSignatureFormAuthenticator.java
federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/api/saml/v2/response/SAML2Response.java
federation/trunk/picketlink-fed-api/src/test/java/org/picketlink/test/identity/federation/api/util/XMLEncryptionUnitTestCase.java
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/saml/SAMLResponseParser.java
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/util/DocumentUtil.java
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/writers/SAMLResponseWriter.java
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/util/XMLEncryptionUtil.java
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/assertion/EncryptedAssertionType.java
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/assertion/EncryptedElementType.java
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/protocol/ResponseType.java
federation/trunk/picketlink-web/pom.xml
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/filters/SPFilter.java
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/process/ServiceProviderSAMLResponseProcessor.java
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/servlets/IDPServlet.java
Log:
PLFED-137: handle encrypted assertions
Modified:
federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/bindings/tomcat/idp/IDPWebBrowserSSOValve.java
===================================================================
---
federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/bindings/tomcat/idp/IDPWebBrowserSSOValve.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/bindings/tomcat/idp/IDPWebBrowserSSOValve.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -395,7 +395,7 @@
requestOptions.put(GeneralConstants.ASSERTIONS_VALIDITY,
this.assertionValidity);
requestOptions.put(GeneralConstants.CONFIGURATION,
this.idpConfiguration);
if( assertionID != null )
- requestOptions.put(GeneralConstants.ASSERTION_ID, assertionID );
+ requestOptions.put(GeneralConstants.ASSERTION_ID, assertionID );
if(this.keyManager != null)
{
@@ -406,6 +406,7 @@
}
PublicKey validatingKey =
CoreConfigUtil.getValidatingKey(keyManager, remoteHost );
requestOptions.put(GeneralConstants.SENDER_PUBLIC_KEY,
validatingKey);
+ requestOptions.put( GeneralConstants.DECRYPTING_KEY,
keyManager.getSigningKey() );
}
Map<String,Object> attribs =
this.attribManager.getAttributes(userPrincipal, attributeKeys);
Modified:
federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/bindings/tomcat/sp/SPRedirectSignatureFormAuthenticator.java
===================================================================
---
federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/bindings/tomcat/sp/SPRedirectSignatureFormAuthenticator.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-bindings/src/main/java/org/picketlink/identity/federation/bindings/tomcat/sp/SPRedirectSignatureFormAuthenticator.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -193,9 +193,7 @@
EncryptedElementType myEET = (EncryptedElementType)
responseType.getAssertions().get(0).getEncryptedAssertion();
Document eetDoc = saml2Response.convert(myEET);
- Element decryptedDocumentElement =
XMLEncryptionUtil.decryptElementInDocument(eetDoc,privateKey);
-
- //Let us use the encrypted doc element to decrypt it
+ Element decryptedDocumentElement =
XMLEncryptionUtil.decryptElementInDocument(eetDoc,privateKey);
return
saml2Response.getResponseType(DocumentUtil.getNodeAsStream(decryptedDocumentElement));
}
catch (Exception e)
Modified:
federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/api/saml/v2/response/SAML2Response.java
===================================================================
---
federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/api/saml/v2/response/SAML2Response.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/api/saml/v2/response/SAML2Response.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -71,6 +71,7 @@
import org.picketlink.identity.federation.newmodel.saml.v2.protocol.StatusResponseType;
import org.picketlink.identity.federation.saml.v2.SAML2Object;
import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
@@ -234,6 +235,20 @@
{
return JBossSAMLAuthnResponseFactory.createResponseType(ID, issuerInfo,
assertion);
}
+
+ /**
+ * Create a ResponseType
+ * @param ID
+ * @param issuerInfo
+ * @param encryptedAssertion a DOM {@link Element} that represents an encrypted
assertion
+ * @return
+ * @throws ConfigurationException
+ */
+ public ResponseType createResponseType(String ID, IssuerInfoHolder issuerInfo, Element
encryptedAssertion)
+ throws ConfigurationException
+ {
+ return JBossSAMLAuthnResponseFactory.createResponseType(ID, issuerInfo,
encryptedAssertion);
+ }
/**
* Add validity conditions to the SAML2 Assertion
Modified:
federation/trunk/picketlink-fed-api/src/test/java/org/picketlink/test/identity/federation/api/util/XMLEncryptionUnitTestCase.java
===================================================================
---
federation/trunk/picketlink-fed-api/src/test/java/org/picketlink/test/identity/federation/api/util/XMLEncryptionUnitTestCase.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-fed-api/src/test/java/org/picketlink/test/identity/federation/api/util/XMLEncryptionUnitTestCase.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -83,6 +83,8 @@
Element docElement =
XMLEncryptionUtil.encryptElementInDocument(responseDoc,kp.getPublic(), sk,
128, assertionQName, true);
+ System.out.println( DocumentUtil.getDOMElementAsString(docElement));
+
// System.out.println( DocumentUtil.getNodeAsString(docElement));
InputStream is = DocumentUtil.getNodeAsStream( docElement );
@@ -95,7 +97,7 @@
Document eetDoc = sr.convert( encryptedAssertionType );
Element decryptedDocumentElement =
XMLEncryptionUtil.decryptElementInDocument(eetDoc,kp.getPrivate());
-
+
//Let us use the encrypted doc element to decrypt it
ResponseType newRT =
sr.getResponseType(DocumentUtil.getNodeAsStream(decryptedDocumentElement));
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/saml/SAMLResponseParser.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/saml/SAMLResponseParser.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/saml/SAMLResponseParser.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -32,9 +32,11 @@
import org.picketlink.identity.federation.core.saml.v2.constants.JBossSAMLConstants;
import org.picketlink.identity.federation.core.saml.v2.constants.JBossSAMLURIConstants;
import org.picketlink.identity.federation.newmodel.saml.v2.assertion.AssertionType;
+import
org.picketlink.identity.federation.newmodel.saml.v2.assertion.EncryptedAssertionType;
import org.picketlink.identity.federation.newmodel.saml.v2.assertion.NameIDType;
import org.picketlink.identity.federation.newmodel.saml.v2.protocol.ResponseType;
import
org.picketlink.identity.federation.newmodel.saml.v2.protocol.ResponseType.RTChoiceType;
+import org.w3c.dom.Element;
/**
* Parse the SAML Response
@@ -84,6 +86,13 @@
{
response.setStatus( parseStatus(xmlEventReader) );
}
+ else if( JBossSAMLConstants.ENCRYPTED_ASSERTION.get().equals( elementName ))
+ {
+ Element encryptedAssertion = StaxParserUtil.getDOMElement(xmlEventReader);
+ response.addAssertion( new RTChoiceType( new
EncryptedAssertionType(encryptedAssertion ) ));
+ }
+ else
+ throw new RuntimeException( "Unknown tag=" + elementName );
}
return response;
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -34,6 +34,7 @@
import org.picketlink.identity.federation.core.saml.v2.util.XMLTimeUtil;
import org.picketlink.identity.federation.newmodel.saml.v2.assertion.AssertionType;
import org.picketlink.identity.federation.newmodel.saml.v2.assertion.ConditionsType;
+import
org.picketlink.identity.federation.newmodel.saml.v2.assertion.EncryptedAssertionType;
import org.picketlink.identity.federation.newmodel.saml.v2.assertion.NameIDType;
import
org.picketlink.identity.federation.newmodel.saml.v2.assertion.StatementAbstractType;
import
org.picketlink.identity.federation.newmodel.saml.v2.assertion.SubjectConfirmationDataType;
@@ -43,6 +44,7 @@
import
org.picketlink.identity.federation.newmodel.saml.v2.protocol.ResponseType.RTChoiceType;
import org.picketlink.identity.federation.newmodel.saml.v2.protocol.StatusCodeType;
import org.picketlink.identity.federation.newmodel.saml.v2.protocol.StatusType;
+import org.w3c.dom.Element;
/**
* Factory for the SAML v2 Authn Response
@@ -168,4 +170,42 @@
responseType.addAssertion( new RTChoiceType( assertionType ));
return responseType;
}
+
+ /**
+ * Create a Response Type
+ * @param ID
+ * @param issuerInfo
+ * @param encryptedAssertion a DOM {@link Element} that represents an encrypted
assertion
+ * @return
+ * @throws ConfigurationException
+ */
+ public static ResponseType createResponseType(String ID, IssuerInfoHolder issuerInfo,
Element encryptedAssertion )
+ throws ConfigurationException
+ {
+ ResponseType responseType = new ResponseType();
+ responseType.setVersion(issuerInfo.getSamlVersion());
+
+ //ID
+ responseType.setID(ID);
+
+ //Issuer
+ NameIDType issuer = issuerInfo.getIssuer();
+ responseType.setIssuer(issuer);
+
+ //Status
+ String statusCode = issuerInfo.getStatusCode();
+ if(statusCode == null)
+ throw new IllegalArgumentException("issuerInfo missing status code");
+
+ responseType.setStatus(createStatusType(statusCode) );
+
+ XMLGregorianCalendar issueInstant = XMLTimeUtil.getIssueInstant();
+
+ //IssueInstant
+ responseType.setIssueInstant(issueInstant);
+
+
+ responseType.addAssertion( new RTChoiceType( new EncryptedAssertionType(
encryptedAssertion ) ));
+ return responseType;
+ }
}
\ No newline at end of file
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/util/DocumentUtil.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/util/DocumentUtil.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/util/DocumentUtil.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -30,6 +30,7 @@
import java.io.StringReader;
import java.io.StringWriter;
+import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -267,6 +268,28 @@
return sw.toString();
}
+
+ /**
+ * <p>Get an element from the document given its {@link QName} </p>
+ * <p>First an attempt to get the element based on its namespace is made,
failing which
+ * an element with the localpart ignoring any namespace is returned.</p>
+ * @param doc
+ * @param elementQName
+ * @return
+ */
+ public static Element getElement( Document doc, QName elementQName )
+ {
+ NodeList nl = doc.getElementsByTagNameNS( elementQName.getNamespaceURI(),
elementQName.getLocalPart() );
+ if( nl.getLength() == 0 )
+ {
+ nl = doc.getElementsByTagNameNS( "*", elementQName.getLocalPart() );
+ if( nl.getLength() == 0 )
+ nl = doc.getElementsByTagName( elementQName.getPrefix() + ":" +
elementQName.getLocalPart() );
+ if( nl.getLength() == 0 )
+ return null;
+ }
+ return (Element) nl.item(0);
+ }
/**
* Stream a DOM Node as an input stream
@@ -280,6 +303,13 @@
return getSourceAsStream(new DOMSource(node));
}
+ /**
+ * Get the {@link Source} as an {@link InputStream}
+ * @param source
+ * @return
+ * @throws ConfigurationException
+ * @throws ProcessingException
+ */
public static InputStream getSourceAsStream(Source source) throws
ConfigurationException, ProcessingException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/writers/SAMLResponseWriter.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/writers/SAMLResponseWriter.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/writers/SAMLResponseWriter.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -43,6 +43,7 @@
import org.picketlink.identity.federation.newmodel.saml.v2.protocol.StatusDetailType;
import org.picketlink.identity.federation.newmodel.saml.v2.protocol.StatusResponseType;
import org.picketlink.identity.federation.newmodel.saml.v2.protocol.StatusType;
+import org.w3c.dom.Element;
/**
* Write a SAML Response to stream
@@ -70,6 +71,7 @@
StaxUtil.writeStartElement( writer, PROTOCOL_PREFIX,
JBossSAMLConstants.RESPONSE.get() , PROTOCOL_NSURI.get() );
StaxUtil.writeNameSpace( writer, PROTOCOL_PREFIX, PROTOCOL_NSURI.get() );
+ StaxUtil.writeNameSpace( writer, ASSERTION_PREFIX, ASSERTION_NSURI.get() );
StaxUtil.writeDefaultNameSpace( writer, ASSERTION_NSURI.get() );
writeBaseAttributes( response );
@@ -94,7 +96,8 @@
EncryptedAssertionType encryptedAssertion =
choiceType.getEncryptedAssertion();
if( encryptedAssertion != null )
{
- //Skip
+ Element encElement = encryptedAssertion.getEncryptedElement();
+ StaxUtil.writeDOMElement(writer, encElement);
}
}
}
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/util/XMLEncryptionUtil.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/util/XMLEncryptionUtil.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/util/XMLEncryptionUtil.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -35,6 +35,7 @@
import org.apache.xml.security.encryption.XMLEncryptionException;
import org.picketlink.identity.federation.core.exceptions.ConfigurationException;
import org.picketlink.identity.federation.core.exceptions.ProcessingException;
+import org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -185,10 +186,7 @@
if (wrappingElementPrefix == null || wrappingElementPrefix == "")
throw new IllegalArgumentException("Wrapping element prefix
invalid");
- NodeList elements = document.getElementsByTagName(elementQName.toString());
- if (elements == null || elements.getLength() > 1)
- throw new IllegalStateException("Element was either null or more than
one:" + elements);
- Element documentElement = (Element) elements.item(0);
+ Element documentElement = DocumentUtil.getElement(document , elementQName );
if (documentElement == null)
throw new IllegalStateException("Element could not be found in the
document:" + elementQName.toString());
Modified:
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/assertion/EncryptedAssertionType.java
===================================================================
---
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/assertion/EncryptedAssertionType.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/assertion/EncryptedAssertionType.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -21,6 +21,8 @@
*/
package org.picketlink.identity.federation.newmodel.saml.v2.assertion;
+import org.w3c.dom.Element;
+
/**
* Assertion that is encrypted
* @author Anil.Saldhana(a)redhat.com
@@ -28,4 +30,18 @@
*/
public class EncryptedAssertionType extends EncryptedElementType
{
+ public EncryptedAssertionType()
+ {
+ super();
+ }
+
+ public EncryptedAssertionType(Element el)
+ {
+ super(el);
+ }
+
+ public String getID()
+ {
+ return null;
+ }
}
\ No newline at end of file
Modified:
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/assertion/EncryptedElementType.java
===================================================================
---
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/assertion/EncryptedElementType.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/assertion/EncryptedElementType.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -39,8 +39,17 @@
</complexType>
*/
- private Element encryptedElement;
+ protected Element encryptedElement;
+ public EncryptedElementType()
+ {
+ }
+
+ public EncryptedElementType( Element el)
+ {
+ this.encryptedElement = el;
+ }
+
public Element getEncryptedElement()
{
return encryptedElement;
Modified:
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/protocol/ResponseType.java
===================================================================
---
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/protocol/ResponseType.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-fed-model/src/main/java/org/picketlink/identity/federation/newmodel/saml/v2/protocol/ResponseType.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -70,6 +70,29 @@
{
assertions.remove(choice);
}
+
+ /**
+ * Replace the first assertion with the passed assertion
+ * @param id id of the old assertion
+ * @param newAssertion
+ */
+ public void replaceAssertion( String id, RTChoiceType newAssertion )
+ {
+ int index = 0;
+ if( id != null && !id.isEmpty())
+ {
+ for( RTChoiceType assertion : assertions )
+ {
+ if( assertion.getID().equals(id) )
+ {
+ break;
+ }
+ index++;
+ }
+ }
+ assertions.remove(index);
+ assertions.add(index, newAssertion);
+ }
/**
* Gets a read only list of assertions
@@ -83,13 +106,16 @@
{
private AssertionType assertion;
private EncryptedAssertionType encryptedAssertion;
+ private String id;
public RTChoiceType(AssertionType assertion)
{
this.assertion = assertion;
+ this.id = assertion.getID();
}
public RTChoiceType(EncryptedAssertionType encryptedAssertion)
{
this.encryptedAssertion = encryptedAssertion;
+
}
public AssertionType getAssertion()
{
@@ -99,5 +125,9 @@
{
return encryptedAssertion;
}
+ public String getID()
+ {
+ return id;
+ }
}
}
\ No newline at end of file
Modified: federation/trunk/picketlink-web/pom.xml
===================================================================
--- federation/trunk/picketlink-web/pom.xml 2011-02-17 19:31:32 UTC (rev 752)
+++ federation/trunk/picketlink-web/pom.xml 2011-02-18 02:28:51 UTC (rev 753)
@@ -33,7 +33,7 @@
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
- <version>2.4.3</version>
+ <version>2.7.1</version>
<configuration>
<printSummary>true</printSummary>
<disableXmlReport>false</disableXmlReport>
@@ -178,6 +178,12 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>xalan</groupId>
+ <artifactId>xalan</artifactId>
+ <version>2.7.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
Modified:
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java
===================================================================
---
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/constants/GeneralConstants.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -48,8 +48,8 @@
String IDENTITY_SERVER = "IDENTITY_SERVER";
String IGNORE_SIGNATURES = "IGNORE_SIGNATURES";
- String KEYPAIR = "KEYPAIR";
-
+ String KEYPAIR = "KEYPAIR";
+
String LOGOUT_PAGE = "LOGOUT_PAGE";
String LOGOUT_PAGE_NAME = "/logout.jsp";
@@ -65,9 +65,10 @@
String SAML_REQUEST_KEY = "SAMLRequest";
String SAML_RESPONSE_KEY = "SAMLResponse";
+ String DECRYPTING_KEY = "DECRYPTING_KEY";
String SENDER_PUBLIC_KEY = "SENDER_PUBLIC_KEY";
String SIGN_OUTGOING_MESSAGES = "SIGN_OUTGOING_MESSAGES";
-
+
String USERNAME_FIELD = "JBID_USERNAME";
String PASS_FIELD = "JBID_PASSWORD";
}
\ No newline at end of file
Modified:
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/filters/SPFilter.java
===================================================================
---
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/filters/SPFilter.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/filters/SPFilter.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -210,7 +210,8 @@
SAML2HandlerRequest saml2HandlerRequest =
new DefaultSAML2HandlerRequest(protocolContext,
holder.getIssuer(), null,
- HANDLER_TYPE.SP);
+ HANDLER_TYPE.SP);
+
SAML2HandlerResponse saml2HandlerResponse = new
DefaultSAML2HandlerResponse();
saml2HandlerResponse.setDestination(identityURL);
@@ -305,6 +306,8 @@
new DefaultSAML2HandlerRequest(protocolContext,
holder.getIssuer(), documentHolder,
HANDLER_TYPE.SP);
+ if( keyManager != null )
+ saml2HandlerRequest.addOption( GeneralConstants.DECRYPTING_KEY,
keyManager.getSigningKey() );
SAML2HandlerResponse saml2HandlerResponse = new
DefaultSAML2HandlerResponse();
@@ -397,6 +400,8 @@
new DefaultSAML2HandlerRequest(protocolContext,
holder.getIssuer(), documentHolder,
HANDLER_TYPE.SP);
+ if( keyManager != null )
+ saml2HandlerRequest.addOption( GeneralConstants.DECRYPTING_KEY,
keyManager.getSigningKey() );
SAML2HandlerResponse saml2HandlerResponse = new
DefaultSAML2HandlerResponse();
Modified:
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java
===================================================================
---
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/handlers/saml2/SAML2AuthenticationHandler.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -23,6 +23,7 @@
import java.io.StringWriter;
import java.security.Principal;
+import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -30,13 +31,17 @@
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
+import javax.xml.namespace.QName;
import org.apache.log4j.Logger;
import org.picketlink.identity.federation.api.saml.v2.request.SAML2Request;
import org.picketlink.identity.federation.api.saml.v2.response.SAML2Response;
import org.picketlink.identity.federation.core.exceptions.ConfigurationException;
import org.picketlink.identity.federation.core.exceptions.ProcessingException;
+import org.picketlink.identity.federation.core.parsers.saml.SAMLParser;
+import org.picketlink.identity.federation.core.parsers.util.StaxParserUtil;
import org.picketlink.identity.federation.core.saml.v2.common.IDGenerator;
+import org.picketlink.identity.federation.core.saml.v2.constants.JBossSAMLConstants;
import org.picketlink.identity.federation.core.saml.v2.constants.JBossSAMLURIConstants;
import
org.picketlink.identity.federation.core.saml.v2.exceptions.AssertionExpiredException;
import org.picketlink.identity.federation.core.saml.v2.holders.IDPInfoHolder;
@@ -47,8 +52,10 @@
import
org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerRequest.GENERATE_REQUEST_TYPE;
import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerResponse;
import org.picketlink.identity.federation.core.saml.v2.util.AssertionUtil;
+import org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil;
import org.picketlink.identity.federation.core.saml.v2.util.StatementUtil;
import org.picketlink.identity.federation.core.saml.v2.util.XMLTimeUtil;
+import org.picketlink.identity.federation.core.util.XMLEncryptionUtil;
import org.picketlink.identity.federation.newmodel.saml.v2.assertion.AssertionType;
import
org.picketlink.identity.federation.newmodel.saml.v2.assertion.AttributeStatementType;
import
org.picketlink.identity.federation.newmodel.saml.v2.assertion.AttributeStatementType.ASTChoiceType;
@@ -68,6 +75,7 @@
import org.picketlink.identity.federation.web.core.IdentityServer;
import org.picketlink.identity.federation.web.interfaces.IRoleValidator;
import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
@@ -339,10 +347,13 @@
if(assertions.size() == 0)
throw new IllegalStateException("No assertions in reply from IDP");
+ PrivateKey privateKey = (PrivateKey) request.getOptions().get(
GeneralConstants.DECRYPTING_KEY );
+
Object assertion = assertions.get(0).getEncryptedAssertion();
if(assertion instanceof EncryptedAssertionType)
{
- responseType = this.decryptAssertion(responseType);
+ responseType = this.decryptAssertion(responseType, privateKey );
+ assertion = responseType.getAssertions().get(0).getAssertion();
}
if( assertion == null )
{
@@ -367,9 +378,34 @@
{
}
- private ResponseType decryptAssertion(ResponseType responseType)
+ private ResponseType decryptAssertion(ResponseType responseType, PrivateKey
privateKey ) throws ProcessingException
{
- throw new RuntimeException("This authenticator does not handle
encryption");
+ if( privateKey == null )
+ throw new IllegalArgumentException( "privateKey is null" );
+ SAML2Response saml2Response = new SAML2Response();
+ try
+ {
+ Document doc = saml2Response.convert( responseType );
+
+ Element enc = DocumentUtil.getElement(doc, new QName(
JBossSAMLConstants.ENCRYPTED_ASSERTION.get() ));
+ if( enc == null )
+ throw new ProcessingException( "Null encrypted assertion
element" );
+ String oldID = enc.getAttribute( "ID" );
+ Document newDoc = DocumentUtil.createDocument();
+ Node importedNode = newDoc.importNode(enc, true);
+ newDoc.appendChild(importedNode);
+
+ Element decryptedDocumentElement =
XMLEncryptionUtil.decryptElementInDocument( newDoc, privateKey );
+ SAMLParser parser = new SAMLParser();
+ AssertionType assertion = (AssertionType) parser.parse(
StaxParserUtil.getXMLEventReader(
DocumentUtil.getNodeAsStream(decryptedDocumentElement)));
+
+ responseType.replaceAssertion( oldID, new RTChoiceType(assertion));
+ return responseType;
+ }
+ catch ( Exception e )
+ {
+ throw new ProcessingException( e );
+ }
}
private Principal handleSAMLResponse(ResponseType responseType,
SAML2HandlerResponse response)
Modified:
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/process/ServiceProviderSAMLResponseProcessor.java
===================================================================
---
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/process/ServiceProviderSAMLResponseProcessor.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/process/ServiceProviderSAMLResponseProcessor.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -156,6 +156,7 @@
}
PublicKey validatingKey = CoreConfigUtil.getValidatingKey(keyManager,
remoteHost );
requestOptions.put(GeneralConstants.SENDER_PUBLIC_KEY, validatingKey);
+ requestOptions.put( GeneralConstants.DECRYPTING_KEY,
keyManager.getSigningKey() );
}
saml2HandlerRequest.setOptions(requestOptions);
Modified:
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/servlets/IDPServlet.java
===================================================================
---
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/servlets/IDPServlet.java 2011-02-17
19:31:32 UTC (rev 752)
+++
federation/trunk/picketlink-web/src/main/java/org/picketlink/identity/federation/web/servlets/IDPServlet.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -341,7 +341,8 @@
SAML2HandlerRequest saml2HandlerRequest =
new DefaultSAML2HandlerRequest(protocolContext,
idpIssuer.getIssuer(), samlDocumentHolder,
- HANDLER_TYPE.IDP);
+ HANDLER_TYPE.IDP);
+
saml2HandlerRequest.setRelayState(relayState);
SAML2HandlerResponse saml2HandlerResponse = new
DefaultSAML2HandlerResponse();
@@ -416,7 +417,7 @@
requestOptions.put(GeneralConstants.CONFIGURATION,
this.idpConfiguration);
Map<String,Object> attribs =
this.attribManager.getAttributes(userPrincipal, attributeKeys);
- requestOptions.put(GeneralConstants.ATTRIBUTES, attribs);
+ requestOptions.put(GeneralConstants.ATTRIBUTES, attribs);
saml2HandlerRequest.setOptions(requestOptions);
Added:
federation/trunk/picketlink-web/src/test/java/org/picketlink/test/identity/federation/web/saml/handlers/SAML2AuthenticationHandlerUnitTestCase.java
===================================================================
---
federation/trunk/picketlink-web/src/test/java/org/picketlink/test/identity/federation/web/saml/handlers/SAML2AuthenticationHandlerUnitTestCase.java
(rev 0)
+++
federation/trunk/picketlink-web/src/test/java/org/picketlink/test/identity/federation/web/saml/handlers/SAML2AuthenticationHandlerUnitTestCase.java 2011-02-18
02:28:51 UTC (rev 753)
@@ -0,0 +1,157 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.picketlink.test.identity.federation.web.saml.handlers;
+
+import java.security.KeyPair;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.namespace.QName;
+
+import org.junit.Test;
+import org.picketlink.identity.federation.api.saml.v2.response.SAML2Response;
+import org.picketlink.identity.federation.core.config.SPType;
+import org.picketlink.identity.federation.core.parsers.saml.SAMLParser;
+import org.picketlink.identity.federation.core.saml.v2.common.IDGenerator;
+import org.picketlink.identity.federation.core.saml.v2.common.SAMLDocumentHolder;
+import org.picketlink.identity.federation.core.saml.v2.constants.JBossSAMLURIConstants;
+import org.picketlink.identity.federation.core.saml.v2.holders.IssuerInfoHolder;
+import
org.picketlink.identity.federation.core.saml.v2.impl.DefaultSAML2HandlerChainConfig;
+import org.picketlink.identity.federation.core.saml.v2.impl.DefaultSAML2HandlerConfig;
+import org.picketlink.identity.federation.core.saml.v2.impl.DefaultSAML2HandlerRequest;
+import org.picketlink.identity.federation.core.saml.v2.impl.DefaultSAML2HandlerResponse;
+import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2Handler;
+import
org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerChainConfig;
+import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerConfig;
+import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerRequest;
+import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerResponse;
+import org.picketlink.identity.federation.core.saml.v2.util.AssertionUtil;
+import org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil;
+import org.picketlink.identity.federation.core.util.KeyStoreUtil;
+import org.picketlink.identity.federation.core.util.XMLEncryptionUtil;
+import org.picketlink.identity.federation.core.wstrust.WSTrustUtil;
+import org.picketlink.identity.federation.newmodel.saml.v2.assertion.AssertionType;
+import org.picketlink.identity.federation.newmodel.saml.v2.assertion.NameIDType;
+import org.picketlink.identity.federation.newmodel.saml.v2.assertion.SubjectType;
+import
org.picketlink.identity.federation.newmodel.saml.v2.assertion.SubjectType.STSubType;
+import org.picketlink.identity.federation.newmodel.saml.v2.protocol.ResponseType;
+import org.picketlink.identity.federation.saml.v2.SAML2Object;
+import org.picketlink.identity.federation.web.constants.GeneralConstants;
+import org.picketlink.identity.federation.web.core.HTTPContext;
+import org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler;
+import org.picketlink.test.identity.federation.web.mock.MockHttpServletRequest;
+import org.picketlink.test.identity.federation.web.mock.MockHttpServletResponse;
+import org.picketlink.test.identity.federation.web.mock.MockHttpSession;
+import org.picketlink.test.identity.federation.web.mock.MockServletContext;
+import org.w3c.dom.Document;
+
+/**
+ * Unit test the {@link SAML2AuthenticationHandler}
+ * @author Anil.Saldhana(a)redhat.com
+ * @since Feb 17, 2011
+ */
+public class SAML2AuthenticationHandlerUnitTestCase
+{
+ @Test
+ public void handleEncryptedAssertion() throws Exception
+ {
+ SAML2AuthenticationHandler handler = new SAML2AuthenticationHandler();
+
+ SAML2HandlerChainConfig chainConfig = new DefaultSAML2HandlerChainConfig();
+ SAML2HandlerConfig handlerConfig = new DefaultSAML2HandlerConfig();
+
+ Map<String,Object> chainOptions = new HashMap<String, Object>();
+ SPType spType = new SPType();
+ chainOptions.put(GeneralConstants.CONFIGURATION, spType );
+ chainOptions.put( GeneralConstants.ROLE_VALIDATOR_IGNORE, "true" );
+ chainConfig.set(chainOptions);
+
+ //Initialize the handler
+ handler.initChainConfig(chainConfig);
+ handler.initHandlerConfig(handlerConfig);
+
+ //Create a Protocol Context
+ MockHttpSession session = new MockHttpSession();
+ MockServletContext servletContext = new MockServletContext();
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest(session,
"POST");
+ MockHttpServletResponse servletResponse = new MockHttpServletResponse();
+ HTTPContext httpContext = new HTTPContext(servletRequest, servletResponse,
servletContext);
+
+ SAML2Object saml2Object = new SAML2Object(){};
+
+ KeyPair keypair = KeyStoreUtil.generateKeyPair( "RSA" );
+
+
+ SAML2Response saml2Response = new SAML2Response();
+ IssuerInfoHolder issuerInfoholder = new IssuerInfoHolder( "testIssuer"
);
+
+ AssertionType assertion = AssertionUtil.createAssertion(
IDGenerator.create("ID_") , new NameIDType() );
+ SubjectType assertionSubject = new SubjectType();
+ STSubType subType = new STSubType();
+ NameIDType anil = new NameIDType();
+ anil.setValue( "anil" );
+ subType.addBaseID( anil );
+ assertionSubject.setSubType(subType);
+ assertion.setSubject(assertionSubject);
+
+ ResponseType responseType =
+ saml2Response.createResponseType(IDGenerator.create("ID_"),
issuerInfoholder, assertion);
+
+ String assertionNS = JBossSAMLURIConstants.ASSERTION_NSURI.get();
+
+ QName assertionQName = new QName(assertionNS, "EncryptedAssertion",
"saml");
+ Document responseDoc = saml2Response.convert(responseType);
+
+ byte[] secret = WSTrustUtil.createRandomSecret((int) 128 / 8);
+ SecretKey secretKey = new SecretKeySpec(secret, "AES");
+
+ PublicKey publicKey = keypair.getPublic();
+ XMLEncryptionUtil.encryptElement(new QName(assertionNS, "Assertion",
"saml" ), responseDoc , publicKey, secretKey, 128, assertionQName, true);
+
+ System.out.println( DocumentUtil.asString(responseDoc));
+
+ SAMLParser parser = new SAMLParser();
+ saml2Object = (SAML2Object) parser.parse(
DocumentUtil.getNodeAsStream(responseDoc));
+
+ SAMLDocumentHolder docHolder = new SAMLDocumentHolder(saml2Object, null);
+ IssuerInfoHolder issuerInfo = new
IssuerInfoHolder("http://localhost:8080/idp/");
+ SAML2HandlerRequest request = new DefaultSAML2HandlerRequest(httpContext,
+ issuerInfo.getIssuer(), docHolder, SAML2Handler.HANDLER_TYPE.SP);
+ request.addOption( GeneralConstants.DECRYPTING_KEY, keypair.getPrivate() );
+
+ SAML2HandlerResponse response = new DefaultSAML2HandlerResponse();
+
+ session.setAttribute(GeneralConstants.PRINCIPAL_ID, new Principal()
+ {
+ public String getName()
+ {
+ return "Hi";
+ }});
+
+
+ handler.handleStatusResponseType(request, response);
+ }
+}
\ No newline at end of file