/// <summary> /// GetPostSamlResponse - Returns a Base64 Encoded String with the SamlResponse in it with a Default Signature type. /// </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> /// <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, Models.IdPOptionsModel options) { return(GetPostSamlResponse(recipient, issuer, subject, audience, requestid, nameIdPolicyFormat, storeLocation, storeName, findType, certFile, certPassword, findValue, attributes, SigningHelper.SignatureType.Response, options)); }
/// <summary> /// Signs an XML Document for a Saml Response /// </summary> /// <param name="xml"></param> /// <param name="cert2"></param> /// <param name="referenceId"></param> /// <returns></returns> public static XmlElement SignDoc(XmlDocument doc, X509Certificate2 cert2, string referenceId, string referenceValue, Models.IdPOptionsModel options) { SamlSignedXml sig = new SamlSignedXml(doc, referenceId); // Add the key to the SignedXml xmlDocument. //sig.SigningKey = cert2.PrivateKey; sig.SigningKey = cert2.GetRSAPrivateKey(); if (options.UseSHA256) { //otherwise - defaults to SHA1 sig.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; } // Create a reference to be signed. Reference reference = new Reference(); reference.Uri = String.Empty; reference.Uri = "#" + referenceValue; // Add an enveloped transformation to the reference. XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); //XmlDsigC14NTransform env2 = new XmlDsigC14NTransform(); XmlDsigExcC14NTransform env2 = new XmlDsigExcC14NTransform(); reference.AddTransform(env); reference.AddTransform(env2); if (options.UseSHA256) { reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256"; } // Add the reference to the SignedXml object. sig.AddReference(reference); // Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate). KeyInfo keyInfo = new KeyInfo(); KeyInfoX509Data keyData = new KeyInfoX509Data(cert2); keyInfo.AddClause(keyData); sig.KeyInfo = keyInfo; sig.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl; // Compute the signature. sig.ComputeSignature(); // Get the XML representation of the signature and save it to an XmlElement object. XmlElement xmlDigitalSignature = sig.GetXml(); return(xmlDigitalSignature); }
/// <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); }