/// <summary>
        /// Decrypts an assertion we received from "fælles-offentlige brugerstyring".
        /// </summary>        
        private static void DecryptFOBSAssertion(string file)
        {
            string assertionBase64 = File.ReadAllText(file);
            byte[] assertionBytes = Convert.FromBase64String(assertionBase64);

            XmlDocument doc = new XmlDocument();
            doc.PreserveWhitespace = true;
            doc.Load( new MemoryStream(assertionBytes) );

            XmlNodeList encryptedList =
                doc.GetElementsByTagName(EncryptedAssertion.ELEMENT_NAME, Saml20Constants.ASSERTION);

            Assert.That(encryptedList.Count == 1);

            // Do some mock configuration.
            FederationConfig config = FederationConfig.GetConfig();
            config.AllowedAudienceUris.Audiences.Add("https://saml.safewhere.net");

            SAML20FederationConfig descr = ConfigurationReader.GetConfig<SAML20FederationConfig>();
            descr.Endpoints.metadataLocation = @"Saml20\Protocol\MetadataDocs\FOBS"; // Set it manually.     
            Assert.That(Directory.Exists(descr.Endpoints.metadataLocation));
            descr.Endpoints.Refresh();

            X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\SafewhereTest_SFS.pfx", "test1234");
            Saml20EncryptedAssertion encass = 
                new Saml20EncryptedAssertion((RSA) cert.PrivateKey);

            encass.LoadXml((XmlElement) encryptedList[0]);
            encass.Decrypt();

            // Retrieve metadata                       
            Saml20Assertion assertion = new Saml20Assertion(encass.Assertion.DocumentElement, null, false);

            IDPEndPoint endp = descr.FindEndPoint(assertion.Issuer);
            Assert.IsNotNull(endp, "Endpoint not found");
            Assert.IsNotNull(endp.metadata, "Metadata not found");

            try
            {
                assertion.CheckValid(AssertionUtil.GetTrustedSigners(assertion.Issuer));
                Assert.Fail("Verification should fail. Token does not include its signing key.");
            } catch(InvalidOperationException)
            {}

            Assert.IsNull(assertion.SigningKey, "Signing key is already present on assertion. Modify test.");
            Assert.That(assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endp.metadata.GetKeys(KeyTypes.signing), endp)));
            Assert.IsNotNull(assertion.SigningKey, "Signing key was not set on assertion instance.");             
        }
        public void DecryptPingAssertion()
        {
            // Load the assertion
            XmlDocument doc = new XmlDocument();
            doc.Load(File.OpenRead(@"c:\tmp\pingassertion.txt"));

            XmlElement xe = GetElement(EncryptedAssertion.ELEMENT_NAME, Saml20Constants.ASSERTION, doc);

            XmlDocument doc2 = new XmlDocument();
            doc2.AppendChild(doc2.ImportNode(xe, true));

            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

            store.Open(OpenFlags.ReadOnly);

            X509Certificate2Collection coll = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
                                                                      "CN=SafewhereTest_SFS, O=Safewhere, C=DK", true);

            Assert.That(coll.Count == 1);

            X509Certificate2 cert = coll[0];

            Saml20EncryptedAssertion encass = new Saml20EncryptedAssertion((RSA)cert.PrivateKey, doc2);
            
            encass.Decrypt();
            
            XmlTextWriter writer = new XmlTextWriter(Console.Out);
            writer.Formatting = Formatting.Indented;
            writer.Indentation = 3;
            writer.IndentChar = ' ';

            encass.Assertion.WriteTo(writer);
            writer.Flush();
            
            Saml20Assertion assertion = new Saml20Assertion(encass.Assertion.DocumentElement, AssertionUtil.GetTrustedSigners(encass.Assertion.Attributes["Issuer"].Value), false);

            Assert.That(encass.Assertion != null);

            Console.WriteLine();
            foreach (SamlAttribute attribute in assertion.Attributes)            
                Console.WriteLine(attribute.Name + " : " + attribute.AttributeValue[0]);
            
        }
Exemple #3
0
        /// <summary>
        /// Performs the attribute query against the specified IdP endpoint and adds the resulting attributes to Saml20Identity.Current.
        /// </summary>
        /// <param name="context">The http context.</param>
        /// <param name="endPoint">The IdP to perform the query against.</param>
        /// <param name="nameIdFormat">The nameid format.</param>
        public void PerformQuery(HttpContext context, IDPEndPoint endPoint, string nameIdFormat)
        {
            Trace.TraceMethodCalled(GetType(), "PerformQuery()");

            HttpSOAPBindingBuilder builder = new HttpSOAPBindingBuilder(context);

            NameID name = new NameID();

            name.Value  = Saml20Identity.Current.Name;
            name.Format = nameIdFormat;
            _attrQuery.Subject.Items = new object[] { name };

            _attrQuery.SamlAttribute = _attributes.ToArray();
            XmlDocument query = new XmlDocument();

            query.XmlResolver = null;
            query.LoadXml(Serialization.SerializeToXmlString(_attrQuery));

            var signingCertificate  = FederationConfig.GetConfig().SigningCertificate.GetCertificate();
            var shaHashingAlgorithm = SignatureProviderFactory.ValidateShaHashingAlgorithm(endPoint.ShaHashingAlgorithm);
            var signatureProvider   = SignatureProviderFactory.CreateFromShaHashingAlgorithmName(shaHashingAlgorithm);

            signatureProvider.SignAssertion(query, ID, signingCertificate);
            if (query.FirstChild is XmlDeclaration)
            {
                query.RemoveChild(query.FirstChild);
            }

            Stream s;

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAttrQuery, endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml));
            }

            try
            {
                s = builder.GetResponse(endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml,
                                        endPoint.AttributeQuery);
            }
            catch (Exception e)
            {
                Trace.TraceData(TraceEventType.Error, e.ToString());
                throw;
            }

            HttpSOAPBindingParser parser = new HttpSOAPBindingParser(s);

            Status status = parser.GetStatus();

            if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
            {
                Trace.TraceData(TraceEventType.Error,
                                string.Format(Tracing.AttrQueryStatusError, Serialization.SerializeToXmlString(status)));
                throw new Saml20Exception(status.StatusMessage);
            }

            bool isEncrypted;

            XmlElement xmlAssertion = Saml20SignonHandler.GetAssertion(parser.SamlMessage, out isEncrypted);

            if (isEncrypted)
            {
                Saml20EncryptedAssertion ass =
                    new Saml20EncryptedAssertion(
                        (RSA)FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey);
                ass.LoadXml(xmlAssertion);
                ass.Decrypt();
                xmlAssertion = ass.Assertion.DocumentElement;
            }

            Saml20Assertion assertion =
                new Saml20Assertion(xmlAssertion, null,
                                    AssertionProfile.Core, endPoint.QuirksMode);

            assertion.Validate(DateTime.UtcNow);

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.AttrQueryAssertion, xmlAssertion == null ? string.Empty : xmlAssertion.OuterXml));
            }

            IEnumerable <string> validationFailures;

            if (!assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endPoint.metadata.Keys, endPoint, out validationFailures)))
            {
                Trace.TraceData(TraceEventType.Error, Resources.SignatureInvalid);
                throw new Saml20Exception(Resources.SignatureInvalid);
            }

            foreach (SamlAttribute attr in assertion.Attributes)
            {
                Saml20Identity.Current.AddAttributeFromQuery(attr.Name, attr);
            }
        }
 private static Saml20Assertion CreateDKSaml20TokenFromAssertion(Saml20EncryptedAssertion encAss)
 {
     return new Saml20Assertion(encAss.Assertion.DocumentElement, null, false);
 }
        public void TestAssertionEncryption()
        {
            Saml20EncryptedAssertion encryptedAssertion = new Saml20EncryptedAssertion();
            encryptedAssertion.Assertion = AssertionUtil.GetTestAssertion_01();

            X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234");
            encryptedAssertion.TransportKey = (RSA) cert.PublicKey.Key;

            encryptedAssertion.Encrypt();

            XmlDocument encryptedAssertionXML = encryptedAssertion.GetXml();
            Assert.IsNotNull(encryptedAssertionXML);

            // A number of simple tests until we get some better way to verify the generated encrypted assertion.
            XmlNodeList list;
            list = encryptedAssertionXML.GetElementsByTagName(EncryptedAssertion.ELEMENT_NAME, Saml20Constants.ASSERTION);
            Assert.AreEqual(1, list.Count);

            list = encryptedAssertionXML.GetElementsByTagName(dk.nita.saml20.Schema.XEnc.EncryptedKey.ELEMENT_NAME, Saml20Constants.XENC);
            Assert.AreEqual(1, list.Count);
        }
        public void TestAssertionDecryption_05()
        {
            // Load the assertion
            XmlDocument doc = new XmlDocument();
            doc.Load(File.OpenRead(@"Saml20\Assertions\EncryptedAssertion_05"));

            // Find the transport key.
            X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234");

            Saml20EncryptedAssertion encryptedAssertion = new Saml20EncryptedAssertion((RSA)cert.PrivateKey, doc);
            Assert.IsNull(encryptedAssertion.Assertion); // Check that it does not contain an assertion prior to decryption.
            encryptedAssertion.Decrypt();
            Assert.IsNotNull(encryptedAssertion.Assertion);
            XmlNodeList list;

            // Perform some rudimentary tests on the output.
            list = encryptedAssertion.Assertion.GetElementsByTagName(Assertion.ELEMENT_NAME, Saml20Constants.ASSERTION);
            Assert.AreEqual(1, list.Count);
        }
        public void TestAssertionDecryption_03()
        {
            // Load the assertion
            XmlDocument doc = new XmlDocument();
            doc.Load(File.OpenRead(@"Saml20\Assertions\EncryptedAssertion_03"));

            // Find the transport key.
            X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234");

            Saml20EncryptedAssertion encryptedAssertion = new Saml20EncryptedAssertion((RSA)cert.PrivateKey, doc);
            Assert.IsNull(encryptedAssertion.Assertion); // Check that it does not contain an assertion prior to decryption.
            encryptedAssertion.Decrypt();
            Assert.IsNotNull(encryptedAssertion.Assertion);
        }
        public void TestAlgorithmConfiguration_02()
        {
            Saml20EncryptedAssertion encryptedAssertion = new Saml20EncryptedAssertion();
            encryptedAssertion.SessionKeyAlgorithm = EncryptedXml.XmlEncAES128Url;
            encryptedAssertion.Assertion = AssertionUtil.GetTestAssertion_01();

            X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234");
            encryptedAssertion.TransportKey = (RSA)cert.PublicKey.Key;

            encryptedAssertion.Encrypt();
            XmlDocument encryptedAssertionXML = encryptedAssertion.GetXml();
            Assert.IsNotNull(encryptedAssertionXML);

            // Verify that the EncryptionMethod element is set correctly.
            XmlNodeList list =
                encryptedAssertionXML.GetElementsByTagName(dk.nita.saml20.Schema.XEnc.EncryptedData.ELEMENT_NAME,
                                                           Saml20Constants.XENC);
            Assert.AreEqual(1, list.Count);
            XmlElement el = (XmlElement) list[0];

            // Go through the children and look for the EncryptionMethod element, and verify its algorithm attribute.
            bool encryptionMethodFound = false;
            foreach (XmlNode node in el.ChildNodes)
            {
                if (node.LocalName == dk.nita.saml20.Schema.XEnc.EncryptionMethod.ELEMENT_NAME &&
                    node.NamespaceURI == Saml20Constants.XENC)
                {
                    el = (XmlElement) node;
                    Assert.AreEqual(EncryptedXml.XmlEncAES128Url, el.GetAttribute("Algorithm"));
                    encryptionMethodFound = true;
                }
            }
            Assert.That(encryptionMethodFound, "Unable to find EncryptionMethod element in EncryptedData.");

            // Now decrypt the assertion, and verify that it recognizes the Algorithm used.
            Saml20EncryptedAssertion decrypter = new Saml20EncryptedAssertion((RSA) cert.PrivateKey);
            Assert.IsNull(decrypter.Assertion);
            decrypter.LoadXml(encryptedAssertionXML.DocumentElement);
            // Set a wrong algorithm and make sure that the class gets it algorithm info from the assertion itself.
            decrypter.SessionKeyAlgorithm = EncryptedXml.XmlEncTripleDESUrl;
            decrypter.Decrypt();
            // Verify that the class has discovered the correct algorithm and set the SessionKeyAlgorithm property accordingly.
            Assert.AreEqual(EncryptedXml.XmlEncAES128Url, decrypter.SessionKeyAlgorithm);
            Assert.IsNotNull(decrypter.Assertion);
        }
 public void TestAlgorithmConfiguration_01()
 {
     Saml20EncryptedAssertion encryptedAssertion = new Saml20EncryptedAssertion();
     encryptedAssertion.SessionKeyAlgorithm = "RSA";
     Assert.Fail("\"Saml20EncryptedAssertion\" class does not respond to incorrect algorithm identifying URI.");
 }
        /// <summary>
        /// Performs the attribute query against the specified IdP endpoint and adds the resulting attributes to Saml20Identity.Current.
        /// </summary>
        /// <param name="context">The http context.</param>
        /// <param name="endPoint">The IdP to perform the query against.</param>
        /// <param name="nameIdFormat">The nameid format.</param>
        public void PerformQuery(HttpContext context, IDPEndPoint endPoint, string nameIdFormat)
        {
            Trace.TraceMethodCalled(GetType(), "PerformQuery()");

            HttpSOAPBindingBuilder builder = new HttpSOAPBindingBuilder(context);

            NameID name = new NameID();
            name.Value = Saml20Identity.Current.Name;
            name.Format = nameIdFormat;
            _attrQuery.Subject.Items = new object[] { name };

            _attrQuery.SamlAttribute = _attributes.ToArray();
            XmlDocument query = new XmlDocument();
            query.LoadXml(Serialization.SerializeToXmlString(_attrQuery));

            XmlSignatureUtils.SignDocument(query, ID);
            if(query.FirstChild is XmlDeclaration)
                query.RemoveChild(query.FirstChild);

            Stream s;

            if (Trace.ShouldTrace(TraceEventType.Information))
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAttrQuery, endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml));

            try
            {
                 s = builder.GetResponse(endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml,
                                               endPoint.AttributeQuery);

            }catch(Exception e)
            {
                Trace.TraceData(TraceEventType.Error, e.ToString());
                throw;
            }

            HttpSOAPBindingParser parser = new HttpSOAPBindingParser(s);

            Status status = parser.GetStatus();

            if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
            {
                Trace.TraceData(TraceEventType.Error,
                                string.Format(Tracing.AttrQueryStatusError, Serialization.SerializeToXmlString(status)));
                throw new Saml20Exception(status.StatusMessage);
            }

            bool isEncrypted;

            XmlElement xmlAssertion = Saml20SignonHandler.GetAssertion(parser.SamlMessage, out isEncrypted);

            if (isEncrypted)
            {
                Saml20EncryptedAssertion ass =
                    new Saml20EncryptedAssertion(
                        (RSA) FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey);
                ass.LoadXml(xmlAssertion);
                ass.Decrypt();
                xmlAssertion = ass.Assertion.DocumentElement;
            }

            Saml20Assertion assertion =
                    new Saml20Assertion(xmlAssertion, null,
                                        AssertionProfile.Core, endPoint.QuirksMode);

            if(Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.AttrQueryAssertion, xmlAssertion == null ? string.Empty : xmlAssertion.OuterXml));
            }

            if(!assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endPoint.metadata.Keys, endPoint))){
                Trace.TraceData(TraceEventType.Error, Resources.SignatureInvalid);
                throw new Saml20Exception(Resources.SignatureInvalid);
            }

            foreach (SamlAttribute attr in assertion.Attributes)
            {
                Saml20Identity.Current.AddAttributeFromQuery(attr.Name, attr);
            }
        }