/// <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 prettier 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="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()); } }
public static string SerializeAndSignSAMLResponse(ResponseType Response) { // 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. X509Certificate2 certificate = new X509Certificate2(@"C:\Program Files\OpenSSL-Win64\bin\certificate.crt");//SAMLConfiguration.Current.CertificateManager.GetPartnerCertificate(partnerSP); //X509Certificate2 certificate2 = new X509Certificate2(@"C:\Program Files\OpenSSL-Win64\bin\certificate1.pfx", "VSIP@ssw0rd"); //certificate.Import(@"C:\Program Files\OpenSSL-Win64\bin\certificate.crt"); EncryptedData edElement = eXml.Encrypt(elementToEncrypt, certificate); XmlElement encryptedAssertion = xmlResponse.CreateElement("saml", "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); return(xmlResponse.OuterXml); }
/// <summary> /// GetPostSamlResponse - Returns a Base64 Encoded String with the SamlResponse in it. /// </summary> /// <param name="recipient">Recipient</param> /// <param name="issuer">Issuer</param> /// <param name="domain">Domain</param> /// <param name="subject">Subject</param> /// <param name="storeLocation">Certificate Store Location</param> /// <param name="storeName">Certificate Store Name</param> /// <param name="findType">Certificate Find Type</param> /// <param name="certLocation">Certificate Location</param> /// <param name="findValue">Certificate Find Value</param> /// <param name="certFile">Certificate File (used instead of the above Certificate Parameters)</param> /// <param name="certPassword">Certificate Password (used instead of the above Certificate Parameters)</param> /// <param name="attributes">A list of attributes to pass</param> /// <param name="signatureType">Whether to sign Response or Assertion</param> /// <returns>A base64Encoded string with a SAML response.</returns> public static string GetPostSamlResponse(string recipient, string issuer, string domain, string subject, StoreLocation storeLocation, StoreName storeName, X509FindType findType, string certFile, string certPassword, object findValue, Dictionary <string, string> attributes, SigningHelper.SignatureType signatureType) { ResponseType response = new ResponseType(); // Response Main Area response.ID = "_" + Guid.NewGuid().ToString(); response.Destination = recipient; response.Version = "2.0"; response.IssueInstant = System.DateTime.UtcNow; NameIDType issuerForResponse = new NameIDType(); issuerForResponse.Value = issuer.Trim(); response.Issuer = issuerForResponse; StatusType status = new StatusType(); status.StatusCode = new StatusCodeType(); status.StatusCode.Value = "urn:oasis:names:tc:SAML:2.0:status:Success"; response.Status = status; XmlSerializer responseSerializer = new XmlSerializer(response.GetType()); StringWriter stringWriter = new StringWriter(); XmlWriterSettings settings = new XmlWriterSettings(); settings.OmitXmlDeclaration = true; settings.Indent = true; settings.Encoding = Encoding.UTF8; XmlWriter responseWriter = XmlTextWriter.Create(stringWriter, settings); string samlString = string.Empty; AssertionType assertionType = SamlHelper.CreateSamlAssertion( issuer.Trim(), recipient.Trim(), domain.Trim(), subject.Trim(), attributes); response.Items = new AssertionType[] { assertionType }; responseSerializer.Serialize(responseWriter, response); responseWriter.Close(); samlString = stringWriter.ToString(); samlString = samlString.Replace("SubjectConfirmationData", string.Format("SubjectConfirmationData NotOnOrAfter=\"{0:o}\" Recipient=\"{1}\"", DateTime.UtcNow.AddMinutes(5), recipient)); stringWriter.Close(); XmlDocument doc = new XmlDocument(); doc.LoadXml(samlString); X509Certificate2 cert = null; if (System.IO.File.Exists(certFile)) { cert = new X509Certificate2(certFile, certPassword); } else { X509Store store = new X509Store(storeName, storeLocation); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection coll = store.Certificates.Find(findType, findValue, true); if (coll.Count < 1) { throw new ArgumentException("Unable to locate certificate"); } cert = coll[0]; store.Close(); } XmlElement signature = SigningHelper.SignDoc(doc, cert, "ID", (signatureType == SigningHelper.SignatureType.Response || signatureType == SigningHelper.SignatureType.TestVU475445) ? response.ID : assertionType.ID); doc.DocumentElement.InsertBefore(signature, doc.DocumentElement.ChildNodes[1]); if (SamlHelper.Logger.IsDebugEnabled) { SamlHelper.Logger.DebugFormat( "Saml Assertion before encoding = {0}", doc.OuterXml.ToString()); } string responseStr = doc.OuterXml; // 2018Ma06 Special Post-signature Maniuplation postsignature to inject comment into subject. if (signatureType == SigningHelper.SignatureType.TestVU475445) { string sub = subject.Trim(); int half = sub.Length / 2; string firstHalf = sub.Substring(0, half); string secondHalf = sub.Substring(half); responseStr = responseStr.Replace(sub, firstHalf + "<!--VU475445-->" + secondHalf); int breaker = 1; } byte[] base64EncodedBytes = Encoding.UTF8.GetBytes(responseStr); string returnValue = System.Convert.ToBase64String( base64EncodedBytes); return(returnValue); }
/// <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); }
public static XmlElement GetSignature(string recipient, string issuer, string domain, string subject, StoreLocation storeLocation, StoreName storeName, X509FindType findType, string certFile, string certPassword, object findValue, Dictionary <string, string> attributes, SigningHelper.SignatureType signatureType) { ResponseType response = new ResponseType(); // Response Main Area response.ID = "_" + Guid.NewGuid().ToString(); response.Destination = recipient; response.Version = "2.0"; response.IssueInstant = System.DateTime.UtcNow; NameIDType issuerForResponse = new NameIDType(); issuerForResponse.Value = issuer.Trim(); response.Issuer = issuerForResponse; StatusType status = new StatusType(); status.StatusCode = new StatusCodeType(); status.StatusCode.Value = "urn:oasis:names:tc:SAML:2.0:status:Success"; response.Status = status; XmlSerializer responseSerializer = new XmlSerializer(response.GetType()); StringWriter stringWriter = new StringWriter(); XmlWriterSettings settings = new XmlWriterSettings(); settings.OmitXmlDeclaration = true; settings.Indent = true; settings.Encoding = Encoding.UTF8; XmlWriter responseWriter = XmlTextWriter.Create(stringWriter, settings); string samlString = string.Empty; AssertionType assertionType = CreateSamlAssertion( issuer.Trim(), recipient.Trim(), domain.Trim(), subject.Trim(), attributes); response.Items = new AssertionType[] { assertionType }; responseSerializer.Serialize(responseWriter, response); responseWriter.Close(); samlString = stringWriter.ToString(); samlString = samlString.Replace("SubjectConfirmationData", string.Format("SubjectConfirmationData NotOnOrAfter=\"{0:o}\" Recipient=\"{1}\"", DateTime.UtcNow.AddMinutes(5), recipient)); stringWriter.Close(); XmlDocument doc = new XmlDocument(); doc.LoadXml(samlString); X509Certificate2 cert = null; cert = new X509Certificate2(certFile, certPassword); XmlElement signature = SigningHelper.SignDoc(doc, cert, "ID", signatureType == SigningHelper.SignatureType.Response ? response.ID : assertionType.ID); return(signature); }
/// <summary> /// GetPostSamlResponse - Returns a Base64 Encoded String with the SamlResponse in it. /// </summary> /// <param name="recipient">Recipient</param> /// <param name="issuer">Issuer</param> /// <param name="domain">Domain</param> /// <param name="subject">Subject</param> /// <param name="storeLocation">Certificate Store Location</param> /// <param name="storeName">Certificate Store Name</param> /// <param name="findType">Certificate Find Type</param> /// <param name="certLocation">Certificate Location</param> /// <param name="findValue">Certificate Find Value</param> /// <param name="certFile">Certificate File (used instead of the above Certificate Parameters)</param> /// <param name="certPassword">Certificate Password (used instead of the above Certificate Parameters)</param> /// <param name="attributes">A list of attributes to pass</param> /// <param name="signatureType">Whether to sign Response or Assertion</param> /// <returns>A base64Encoded string with a SAML response.</returns> public static string BuildPostSamlResponse(string recipient, string issuer, string domain, string subject, StoreLocation storeLocation, StoreName storeName, X509FindType findType, string certFile, string certPassword, object findValue, Dictionary <string, string> attributes, SigningHelper.SignatureType signatureType) { ResponseType response = new ResponseType { // Response Main Area ID = "_" + Guid.NewGuid().ToString(), Destination = recipient, Version = "2.0", IssueInstant = DateTime.UtcNow }; NameIDType issuerForResponse = new NameIDType { Value = issuer.Trim() }; response.Issuer = issuerForResponse; StatusType status = new StatusType { StatusCode = new StatusCodeType() }; status.StatusCode.Value = "urn:oasis:names:tc:SAML:2.0:status:Success"; response.Status = status; XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("saml2p", "urn:oasis:names:tc:SAML:2.0:protocol"); ns.Add("saml2", "urn:oasis:names:tc:SAML:2.0:assertion"); XmlSerializer responseSerializer = new XmlSerializer(response.GetType()); StringWriter stringWriter = new StringWriter(); XmlWriterSettings settings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true, Encoding = Encoding.UTF8 }; XmlWriter responseWriter = XmlWriter.Create(stringWriter, settings); string samlString = string.Empty; AssertionType assertionType = Saml2Helper.CreateSamlAssertion( issuer.Trim(), recipient.Trim(), domain.Trim(), subject.Trim(), attributes); response.Items = new AssertionType[] { assertionType }; responseSerializer.Serialize(responseWriter, response, ns); responseWriter.Close(); samlString = stringWriter.ToString(); samlString = samlString.Replace("SubjectConfirmationData", string.Format("SubjectConfirmationData NotOnOrAfter=\"{0:o}\" Recipient=\"{1}\"", DateTime.UtcNow.AddMinutes(5), recipient)); samlString = samlString.Replace("<saml2:Assertion ", "<saml2:Assertion xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\" "); samlString = samlString.Replace("<saml2:AuthnContextClassRef>AuthnContextClassRef</saml2:AuthnContextClassRef>", "<saml2:AuthnContextClassRef>" + issuer + "</saml2:AuthnContextClassRef>"); stringWriter.Close(); XmlDocument doc = new XmlDocument(); doc.LoadXml(samlString); X509Certificate2 cert = null; if (System.IO.File.Exists(certFile)) { cert = new X509Certificate2(certFile, certPassword); } else { X509Store store = new X509Store(storeName, storeLocation); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); X509Certificate2Collection CertCol = store.Certificates; //foreach (X509Certificate2 c in CertCol) //{ // if (c.Subject.Contains(findValue.ToString())) // { // cert = c; // break; // } //} X509Certificate2Collection coll = store.Certificates.Find(findType, findValue.ToString(), false); //if (cert == null) //{ // throw new ArgumentException("Unable to locate certificate"); //} if (coll.Count < 1) { throw new ArgumentException("Unable to locate certificate"); } cert = coll[0]; store.Close(); } XmlElement signature = SigningHelper.SignDoc(doc, cert, response.ID); doc.DocumentElement.InsertBefore(signature, doc.DocumentElement.ChildNodes[1]); string responseStr = doc.OuterXml; byte[] base64EncodedBytes = Encoding.UTF8.GetBytes(responseStr); string returnValue = System.Convert.ToBase64String( base64EncodedBytes); return(returnValue); }
/// <summary> /// GetPostSamlResponse - Returns a Base64 Encoded String with the SamlResponse in it. /// </summary> /// <param name="recipient">Recipient</param> /// <param name="issuer">Issuer</param> /// <param name="domain">Domain</param> /// <param name="subject">Subject</param> /// <param name="storeLocation">Certificate Store Location</param> /// <param name="storeName">Certificate Store Name</param> /// <param name="findType">Certificate Find Type</param> /// <param name="certLocation">Certificate Location</param> /// <param name="findValue">Certificate Find Value</param> /// <param name="certFile">Certificate File (used instead of the above Certificate Parameters)</param> /// <param name="certPassword">Certificate Password (used instead of the above Certificate Parameters)</param> /// <param name="attributes">A list of attributes to pass</param> /// <param name="signatureType">Whether to sign Response or Assertion</param> /// <returns>A base64Encoded string with a SAML response.</returns> public static string GetPostSamlResponse(string recipient, string issuer, string subject, string audience, string requestid, string nameIdPolicyFormat, StoreLocation storeLocation, StoreName storeName, X509FindType findType, string certFile, string certPassword, object findValue, Dictionary <string, string> attributes, SigningHelper.SignatureType signatureType, Models.IdPOptionsModel options) { ResponseType response = new ResponseType(); // Response Main Area response.ID = "_" + Guid.NewGuid().ToString("N"); response.Destination = recipient; response.Version = "2.0"; response.IssueInstant = System.DateTime.UtcNow; response.InResponseTo = requestid; NameIDType issuerForResponse = new NameIDType(); issuerForResponse.Value = issuer.Trim(); response.Issuer = issuerForResponse; StatusType status = new StatusType(); status.StatusCode = new StatusCodeType(); status.StatusCode.Value = "urn:oasis:names:tc:SAML:2.0:status:Success"; response.Status = status; XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); if (options.UseNamespaces) { ns.Add("saml2p", "urn:oasis:names:tc:SAML:2.0:protocol"); ns.Add("saml2", "urn:oasis:names:tc:SAML:2.0:assertion"); ns.Add("ds", "http://www.w3.org/2000/09/xmldsig#"); } XmlSerializer responseSerializer = new XmlSerializer(response.GetType()); StringWriter stringWriter = new StringWriter(); XmlWriterSettings settings = new XmlWriterSettings(); settings.Encoding = Encoding.UTF8; settings.OmitXmlDeclaration = true; settings.Indent = true; XmlWriter responseWriter = XmlTextWriter.Create(stringWriter, settings); string samlString = string.Empty; AssertionType assertionType = SamlHelper.CreateSamlAssertion( issuer.Trim(), recipient.Trim(), subject.Trim(), audience.Trim(), nameIdPolicyFormat, attributes); response.Items = new AssertionType[] { assertionType }; responseSerializer.Serialize(responseWriter, response, ns); responseWriter.Close(); samlString = stringWriter.ToString(); samlString = samlString.Replace("SubjectConfirmationData", string.Format("SubjectConfirmationData NotOnOrAfter=\"{0:o}\" Recipient=\"{1}\" InResponseTo=\"{2:D}\" ", DateTime.UtcNow.AddMinutes(5), recipient, requestid)); stringWriter.Close(); XmlDocument doc = new XmlDocument(); //doc.LoadXml(samlString); byte[] samlBytes = Encoding.UTF8.GetBytes(samlString); var ms = new MemoryStream(samlBytes); doc.Load(ms); X509Certificate2 cert = null; if (System.IO.File.Exists(certFile)) { try { cert = new X509Certificate2(certFile, certPassword); } catch (Exception ex) { ; } } else { X509Store store = new X509Store(storeName, storeLocation); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection coll = store.Certificates.Find(findType, findValue, false); if (coll.Count < 1) { throw new ArgumentException("Unable to locate certificate"); } cert = coll[0]; store.Close(); } XmlElement signature = SigningHelper.SignDoc(doc, cert, "ID", signatureType == SigningHelper.SignatureType.Response ? response.ID : assertionType.ID, options); doc.DocumentElement.InsertBefore(signature, doc.DocumentElement.ChildNodes[1]); if (SamlHelper.Logger.IsDebugEnabled) { SamlHelper.Logger.DebugFormat( "Saml Assertion before encoding = {0}", doc.OuterXml.ToString()); } //string responseStr = doc.OuterXml; //byte[] base64EncodedBytes = // Encoding.UTF8.GetBytes(responseStr); if (options.IncludeXmlDeclaration) { //Create an XML declaration. XmlDeclaration xmldecl; xmldecl = doc.CreateXmlDeclaration("1.0", "UTF-8", "no"); //Add the new node to the document. XmlElement root = doc.DocumentElement; doc.InsertBefore(xmldecl, root); } byte[] base64EncodedBytes = Encoding.UTF8.GetBytes(doc.OuterXml); string returnValue = System.Convert.ToBase64String( base64EncodedBytes); return(returnValue); }
/// <summary> /// Returns a Base64 Encoded String with the SamlResponse in it. /// </summary> /// <param name="recipient">Recipient</param> /// <param name="issuer">Issuer</param> /// <param name="subject">Subject</param> /// <param name="certLocation">Certificate Location</param> /// <param name="certPassword">Certificate Password</param> /// <param name="attributes">A list of attributes to pass</param> /// <returns></returns> public static string GetPostSamlResponse(string recipient, string issuer, string domain, string subject, StoreLocation storeLocation, StoreName storeName, X509FindType findType, string certFile, string certPassword, object findValue, Dictionary <string, string> attributes, SigningHelper.SignatureType signatureType) { ResponseType response = new ResponseType(); // Create Response response.ResponseID = "_" + Guid.NewGuid().ToString(); response.MajorVersion = "1"; response.MinorVersion = "1"; response.IssueInstant = System.DateTime.UtcNow; response.Recipient = recipient; StatusType status = new StatusType(); status.StatusCode = new StatusCodeType(); status.StatusCode.Value = new XmlQualifiedName("Success", "urn:oasis:names:tc:SAML:1.0:protocol"); response.Status = status; // Create Assertion AssertionType assertionType = SamlHelper.CreateSaml11Assertion( issuer.Trim(), domain.Trim(), subject.Trim(), attributes); response.Assertion = new AssertionType[] { assertionType }; //Serialize XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("samlp", "urn:oasis:names:tc:SAML:1.0:protocol"); ns.Add("saml", "urn:oasis:names:tc:SAML:1.0:assertion"); XmlSerializer responseSerializer = new XmlSerializer(response.GetType()); StringWriter stringWriter = new StringWriter(); XmlWriterSettings settings = new XmlWriterSettings(); settings.OmitXmlDeclaration = true; settings.Indent = true; settings.Encoding = Encoding.UTF8; XmlWriter responseWriter = XmlTextWriter.Create(stringWriter, settings); responseSerializer.Serialize(responseWriter, response, ns); responseWriter.Close(); string samlString = stringWriter.ToString(); stringWriter.Close(); // Sign the document XmlDocument doc = new XmlDocument(); doc.LoadXml(samlString); X509Certificate2 cert = null; if (System.IO.File.Exists(certFile)) { cert = new X509Certificate2(certFile, certPassword); } else { X509Store store = new X509Store(storeName, storeLocation); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection coll = store.Certificates.Find(findType, findValue, true); if (coll.Count < 1) { throw new ArgumentException("Unable to locate certificate"); } cert = coll[0]; store.Close(); } XmlElement signature = SigningHelper.SignDoc( doc, cert, "ResponseID", response.ResponseID); doc.DocumentElement.InsertBefore(signature, doc.DocumentElement.ChildNodes[0]); if (SamlHelper.Logger.IsDebugEnabled) { SamlHelper.Logger.DebugFormat( "Saml Assertion before encoding = {0}", doc.OuterXml.ToString()); } // Base64Encode and URL Encode byte[] base64EncodedBytes = Encoding.UTF8.GetBytes(doc.OuterXml); string returnValue = System.Convert.ToBase64String( base64EncodedBytes); return(returnValue); }