/// <summary> /// Accepts SAML Response, serializes it to XML and signs using the supplied certificate /// </summary> /// <param name="Response">SAML 2.0 Response</param> /// <param name="SigningCert">X509 certificate</param> /// <returns>XML Document with computed signature</returns> private static XmlDocument SerializeAndSignSAMLResponse(ResponseType Response, X509Certificate2 SigningCert) { // Set serializer and writers for action XmlSerializer responseSerializer = new XmlSerializer(Response.GetType()); StringWriter stringWriter = new StringWriter(); XmlWriter responseWriter = XmlTextWriter.Create(stringWriter, new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true, Encoding = Encoding.UTF8 }); responseSerializer.Serialize(responseWriter, Response); responseWriter.Close(); XmlDocument xmlResponse = new XmlDocument(); xmlResponse.LoadXml(stringWriter.ToString()); // Set the namespace for prettire and more consistent XML XmlNamespaceManager ns = new XmlNamespaceManager(xmlResponse.NameTable); ns.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion"); CertificateUtility.AppendSignatureToXMLDocument(ref xmlResponse, "#" + ((AssertionType)Response.Items[0]).ID, SigningCert); return(xmlResponse); }
/// <summary> /// Accepts SAML Response, serializes it to XML and signs using the supplied certificate /// </summary> /// <param name="Response">SAML 2.0 Response</param> /// <param name="SigningCert">X509 certificate</param> /// <returns>XML Document with computed signature</returns> private static XmlDocument SerializeAndSignSAMLResponse(ResponseType Response, string partnerSP) { // Set serializer and writers for action XmlSerializer responseSerializer = new XmlSerializer(Response.GetType()); StringWriter stringWriter = new StringWriter(); XmlWriter responseWriter = XmlTextWriter.Create(stringWriter, new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true, Encoding = Encoding.UTF8 }); responseSerializer.Serialize(responseWriter, Response); responseWriter.Close(); XmlDocument xmlResponse = new XmlDocument(); xmlResponse.LoadXml(stringWriter.ToString()); XmlElement elementToEncrypt = xmlResponse.GetElementsByTagName("saml:Assertion")[0] as XmlElement; ////////////////////////////////////////////////// // Create a new instance of the EncryptedXml class // and use it to encrypt the XmlElement with the // X.509 Certificate. ////////////////////////////////////////////////// EncryptedXml eXml = new EncryptedXml(); // Encrypt the element. var certificate = SAMLConfiguration.Current.CertificateManager.GetPartnerCertificate(partnerSP); EncryptedData edElement = eXml.Encrypt(elementToEncrypt, certificate); XmlElement encryptedAssertion = xmlResponse.CreateElement("saml2", "EncryptedAssertion", "urn:oasis:names:tc:SAML:2.0:assertion"); EncryptedXml.ReplaceElement(encryptedAssertion, edElement, true); //////////////////////////////////////////////////// // Replace the element from the original XmlDocument // object with the EncryptedData element. //////////////////////////////////////////////////// xmlResponse.GetElementsByTagName("Response")[0].ReplaceChild(encryptedAssertion, elementToEncrypt); //Get the X509 info XmlElement issuerSerialElement = xmlResponse.CreateElement("ds", "X509IssuerSerial", SignedXml.XmlDsigNamespaceUrl); XmlElement issuerNameElement = xmlResponse.CreateElement("ds", "X509IssuerName", SignedXml.XmlDsigNamespaceUrl); issuerNameElement.AppendChild(xmlResponse.CreateTextNode(certificate.IssuerName.Name)); issuerSerialElement.AppendChild(issuerNameElement); XmlElement serialNumberElement = xmlResponse.CreateElement("ds", "X509SerialNumber", SignedXml.XmlDsigNamespaceUrl); serialNumberElement.AppendChild(xmlResponse.CreateTextNode(certificate.SerialNumber)); issuerSerialElement.AppendChild(serialNumberElement); // Set requested namespaces xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["EncryptedData"].Prefix = "xenc"; xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["EncryptionMethod"].Prefix = "xenc"; xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["KeyInfo"].Prefix = "ds"; xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["ds:KeyInfo"]["EncryptedKey"].Prefix = "xenc"; xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["ds:KeyInfo"]["xenc:EncryptedKey"]["EncryptionMethod"].Prefix = "xenc"; xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["ds:KeyInfo"]["xenc:EncryptedKey"]["CipherData"].Prefix = "xenc"; xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["ds:KeyInfo"]["xenc:EncryptedKey"]["xenc:CipherData"]["CipherValue"].Prefix = "xenc"; xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["ds:KeyInfo"]["xenc:EncryptedKey"]["KeyInfo"].Prefix = "ds"; xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["ds:KeyInfo"]["xenc:EncryptedKey"]["ds:KeyInfo"]["X509Data"].Prefix = "ds"; // We don't need this for MagnaCare xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["ds:KeyInfo"]["xenc:EncryptedKey"]["ds:KeyInfo"]["ds:X509Data"].RemoveChild(xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["ds:KeyInfo"]["xenc:EncryptedKey"]["ds:KeyInfo"]["ds:X509Data"]["X509Certificate"]); xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["CipherData"].Prefix = "xenc"; xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["xenc:CipherData"]["CipherValue"].Prefix = "xenc"; //Add X509 Issuer Info xmlResponse.DocumentElement["saml2:EncryptedAssertion"]["xenc:EncryptedData"]["ds:KeyInfo"]["xenc:EncryptedKey"]["ds:KeyInfo"]["ds:X509Data"].AppendChild(issuerSerialElement); // Set the namespace for prettire and more consistent XML var ns = new XmlNamespaceManager(xmlResponse.NameTable); ns.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion"); ns.AddNamespace("xenc", "http://www.w3.org/2001/04/xmlenc#"); CertificateUtility.AppendSignatureToXMLDocument(ref xmlResponse, "#" + ((AssertionType)Response.Items[0]).ID); return(xmlResponse); }