/// <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="partnerSP"></param> /// <returns>Serialized XML Document with computed signature as byte array.</returns> private static byte[] SerializeAndSignSAMLResponse(ResponseType Response, string partnerSP) { // saml.config contains relative paths not virtual var signatureCertificatePath = HostingEnvironment.MapPath("~/" + SAMLConfiguration.Current.IdentityProviderConfiguration.CertificateFile); var signaruteCertificatePassword = SAMLConfiguration.Current.IdentityProviderConfiguration.CertificatePassword; var encryptionKeyPath = HostingEnvironment.MapPath("~/" + SAMLConfiguration.Current.GetPartnerServiceProvider(partnerSP).CertificateFile); using (var stream = new MemoryStream()) { var ns = new XmlSerializerNamespaces(); // namespace prefixes so that output layout is like in their sample (SAML_Response_Unencoded_IWS_Working.xml) ns.Add("saml2p", "urn:oasis:names:tc:SAML:2.0:protocol"); ns.Add("saml2", "urn:oasis:names:tc:SAML:2.0:assertion"); var responseSerializer = new XmlSerializer(Response.GetType()); responseSerializer.Serialize(stream, Response, ns); stream.Seek(0, SeekOrigin.Begin); FXMLDocument.LoadFromStream(stream); } SBUtils.Unit.SetLicenseKey(File.ReadAllText(HostingEnvironment.MapPath("~/App_Data/eldos-key.txt"))); // Assertion signature var assertionToSign = FXMLDocument.FindNode("saml2:Assertion", true); SignElement(signatureCertificatePath, signaruteCertificatePassword, assertionToSign); Trace.Write(DateTime.Now.ToShortTimeString() + ": SAML plain body:" + assertionToSign.OwnerDocument.OuterXML); // Assertion encryption EncryptAssertion(encryptionKeyPath, assertionToSign); // Response signature var responseToSign = FXMLDocument.FindNode("saml2p:Response", true); SignElement(signatureCertificatePath, signaruteCertificatePassword, responseToSign); using (var stream = new MemoryStream()) { FXMLDocument.SaveToStream(stream, SBXMLDefs.Unit.xcmExclCanonComment, new SBXMLCharsets.TElXMLUTF8Codec { WriteBOM = false }); return stream.ToArray(); } }
/// <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; }
/// <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; }