Пример #1
0
        /// <summary>
        /// Build a signed XML SAML Response string to be inlcuded in an HTML Form
        /// for POSTing to a SAML Service Provider
        /// </summary>
        /// <param name="Issuer">Identity Provider - Used to match the certificate for verifying 
        ///     Response signing</param>
        /// <param name="AssertionExpirationMinutes">Assertion lifetime</param>
        /// <param name="Audience"></param>
        /// <param name="Subject"></param>
        /// <param name="Recipient"></param>
        /// <param name="Attributes">Dictionary of attributes to send through for user SSO</param>
        /// <param name="SigningCert">X509 Certificate used to sign Assertion</param>
        /// <returns></returns>
        public static string CreateSAML20Response(string Issuer,
            int AssertionExpirationMinutes,
            string Audience,
            string Subject,
            string Recipient,
            Dictionary<string, string> Attributes,
            string partnerSP)
        {
            // Create SAML Response object with a unique ID and correct version
            var response = new ResponseType(true)
            {
                ID = "_" + Guid.NewGuid(),
                Version = "2.0",
                IssueInstant = System.DateTime.UtcNow,
                Destination = Recipient.Trim(),
                Issuer = new NameIDType() { Value = Issuer.Trim() },
                Status = new StatusType() { StatusCode = new StatusCodeType() { Value = "urn:oasis:names:tc:SAML:2.0:status:Success" } }
            };

            // Put SAML 2.0 Assertion in Response
            response.Items = new AssertionType[] { CreateSAML20Assertion(Issuer, AssertionExpirationMinutes, Audience, Subject, Recipient, Attributes) };

            XmlDocument XMLResponse = SerializeAndSignSAMLResponse(response, partnerSP);

            return System.Convert.ToBase64String(Encoding.UTF8.GetBytes(XMLResponse.OuterXml));
            //return XMLResponse.OuterXml;
        }
Пример #2
0
        /// <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;
        }
Пример #3
0
        /// <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();
            }
        }
Пример #4
0
        /// <summary>
        /// Build a signed XML SAML Response string to be inlcuded in an HTML Form
        /// for POSTing to a SAML Service Provider
        /// </summary>
        /// <param name="Issuer">Identity Provider - Used to match the certificate for verifying 
        ///     Response signing</param>
        /// <param name="AssertionExpirationMinutes">Assertion lifetime</param>
        /// <param name="Audience"></param>
        /// <param name="Subject"></param>
        /// <param name="Recipient"></param>
        /// <param name="Attributes">Dictionary of attributes to send through for user SSO</param>
        /// <param name="SigningCert">X509 Certificate used to sign Assertion</param>
        /// <returns></returns>
        public static string CreateSAML20ResponseAsBase64(string Issuer,
            int AssertionExpirationMinutes,
            string Audience,
            string Subject,
            string Recipient,
            Dictionary<string, string> Attributes,
            string partnerSP)
        {
            // Create SAML Response object with a unique ID and correct version
            var response = new ResponseType()
            {
                ID = "_" + Guid.NewGuid(),
                Version = "2.0",
                IssueInstant = DateTime.UtcNow,
                Destination = Recipient.Trim(),
                Issuer = new NameIDType() { Value = Issuer.Trim() },
                Status = new StatusType() { StatusCode = new StatusCodeType() { Value = "urn:oasis:names:tc:SAML:2.0:status:Success" } }
            };

            // Put SAML 2.0 Assertion in Response
            response.Items = new AssertionType[] { CreateSAML20Assertion(Issuer, AssertionExpirationMinutes, Audience, Subject, Recipient, Attributes) };

            byte[] binaryResponse = SerializeAndSignSAMLResponse(response, partnerSP);

            Trace.TraceInformation(DateTime.Now.ToShortTimeString() + ": Sending SAML assertion: partner provider=" + partnerSP + ", SAML assertion=" + Encoding.UTF8.GetString(binaryResponse));

            return Convert.ToBase64String(binaryResponse);
        }
        /// <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;
        }