[picketlink-commits] Picketlink SVN: r753 - in federation/trunk: picketlink-bindings/src/main/java/org/picketlink/identity/federation/bindings/tomcat/sp and 16 other directories.

picketlink-commits at lists.jboss.org picketlink-commits at lists.jboss.org
Thu Feb 17 21:28:52 EST 2011


Author: anil.saldhana at 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 at 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 at 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



More information about the picketlink-commits mailing list