public void TestSigning_04() { // Any key-containing algorithm will do - the basic assertion is NOT signed anyway X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234"); new Saml20Assertion(AssertionUtil.GetTestAssertion_01().DocumentElement, new AsymmetricAlgorithm[] { cert.PublicKey.Key }, false); }
public void AuthnStatement_Element() { Assertion saml20Assertion = AssertionUtil.GetBasicAssertion(); AuthnStatement authnStmt = (AuthnStatement)Array.Find(saml20Assertion.Items, delegate(StatementAbstract stmnt) { return(stmnt is AuthnStatement); }); // Mess around with the AuthnStatement. { string oldSessionIndex = authnStmt.SessionIndex; authnStmt.SessionIndex = null; TestAssertion(saml20Assertion, "The DK-SAML 2.0 profile requires that the \"AuthnStatement\" element contains the \"SessionIndex\" attribute."); authnStmt.SessionIndex = oldSessionIndex; } { int index = Array.FindIndex(authnStmt.AuthnContext.Items, delegate(object o) { return(o is string && o.ToString() == "urn:oasis:names:tc:SAML:2.0:ac:classes:X509"); }); object oldValue = authnStmt.AuthnContext.Items[index]; authnStmt.AuthnContext.Items[index] = "Hallelujagobble!!"; TestAssertion(saml20Assertion, "AuthnContextClassRef has a value which is not a wellformed absolute uri"); authnStmt.AuthnContext.Items[index] = oldValue; } // Remove it. saml20Assertion = AssertionUtil.GetBasicAssertion(); List <StatementAbstract> statements = new List <StatementAbstract>(saml20Assertion.Items); statements.RemoveAll(delegate(StatementAbstract stmnt) { return(stmnt is AuthnStatement); }); saml20Assertion.Items = statements.ToArray(); TestAssertion(saml20Assertion, "The DK-SAML 2.0 profile requires exactly one \"AuthnStatement\" element and one \"AttributeStatement\" element."); }
[Ignore] // TODO: test data needs fixing public void AddAttribute_01() { Saml20Assertion assertion = LoadAssertion(@"Saml20\Assertions\Saml2Assertion_01"); List <SamlAttribute> attributes = assertion.Attributes; attributes.Add(DKSaml20PostalAddressAttribute.Create("DK-2200 København")); X509Certificate2 cert = AssertionUtil.GetCertificate1(); assertion.Sign(cert); assertion.CheckValid(new AsymmetricAlgorithm[] { cert.PublicKey.Key }); // Verify that the modified assertion can survive complete serialization and deserialization. string assertionString = assertion.GetXml().OuterXml; XmlDocument deserializedAssertionDoc = new XmlDocument(); deserializedAssertionDoc.PreserveWhitespace = true; deserializedAssertionDoc.Load(new StringReader(assertionString)); Saml20Assertion deserializedAssertion = new Saml20Assertion(deserializedAssertionDoc.DocumentElement, null, false); Assert.IsNotNull(deserializedAssertion.GetSignatureKeys(), "Signing keys must be present"); deserializedAssertion.CheckValid(new AsymmetricAlgorithm[] { cert.PublicKey.Key }); }
[Ignore] // TODO: test data needs fixing public void TestSigning_03() { // Load an unsigned assertion. Saml20Assertion assertion = new Saml20Assertion(AssertionUtil.GetTestAssertion_01().DocumentElement, null, false); // Check that the assertion is not considered valid in any way. try { assertion.CheckValid(AssertionUtil.GetTrustedSigners(assertion.Issuer)); Assert.Fail("Unsigned assertion was passed off as valid."); } catch { //Added to make resharper happy Assert.That(true); } X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234"); Assert.That(cert.HasPrivateKey, "Certificate no longer contains a private key. Modify test."); assertion.Sign(cert); // Check that the signature is now valid assertion.CheckValid(new AsymmetricAlgorithm[] { cert.PublicKey.Key }); WriteToFile(@"\signedassertion.xml", assertion.GetXml()); }
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); }
/// <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 = SAML20FederationConfig.GetConfig(); descr.Endpoints.MetadataLocation = @"Saml20\Protocol\MetadataDocs\FOBS"; // Set it manually. Assert.That(Directory.Exists(descr.Endpoints.MetadataLocation)); 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."); IEnumerable <string> validationFailures; Assert.That(assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endp.metadata.GetKeys(KeyTypes.signing), endp, out validationFailures))); Assert.IsNotNull(assertion.SigningKey, "Signing key was not set on assertion instance."); }
public void TestSigning_01() { XmlDocument token = AssertionUtil.GetTestAssertion_01(); SignDocument(token); bool verified = VerifySignature(token); Assert.That(verified); WriteToFile(@"signedassertion.xml", token.DocumentElement); }
public void GenerateEncryptedAssertion_01() { XmlDocument assertion = AssertionUtil.GetTestAssertion_01(); // Create an EncryptedData instance to hold the results of the encryption.o EncryptedData encryptedData = new EncryptedData(); encryptedData.Type = EncryptedXml.XmlEncElementUrl; encryptedData.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url); // Create a symmetric key. RijndaelManaged aes = new RijndaelManaged(); aes.KeySize = 256; aes.GenerateKey(); // Encrypt the assertion and add it to the encryptedData instance. EncryptedXml encryptedXml = new EncryptedXml(); byte[] encryptedElement = encryptedXml.EncryptData(assertion.DocumentElement, aes, false); encryptedData.CipherData.CipherValue = encryptedElement; // Add an encrypted version of the key used. encryptedData.KeyInfo = new KeyInfo(); EncryptedKey encryptedKey = new EncryptedKey(); // Use this certificate to encrypt the key. X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234"); RSA publicKeyRSA = cert.PublicKey.Key as RSA; Assert.IsNotNull(publicKeyRSA, "Public key of certificate was not an RSA key. Modify test."); encryptedKey.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url); encryptedKey.CipherData = new CipherData(EncryptedXml.EncryptKey(aes.Key, publicKeyRSA, false)); encryptedData.KeyInfo.AddClause(new KeyInfoEncryptedKey(encryptedKey)); // Create the resulting Xml-document to hook into. EncryptedAssertion encryptedAssertion = new EncryptedAssertion(); encryptedAssertion.encryptedData = new saml20.Schema.XEnc.EncryptedData(); encryptedAssertion.encryptedKey = new saml20.Schema.XEnc.EncryptedKey[1]; encryptedAssertion.encryptedKey[0] = new saml20.Schema.XEnc.EncryptedKey(); XmlDocument result; result = Serialization.Serialize(encryptedAssertion); XmlElement encryptedDataElement = GetElement(dk.nita.saml20.Schema.XEnc.EncryptedData.ELEMENT_NAME, Saml20Constants.XENC, result); EncryptedXml.ReplaceElement(encryptedDataElement, encryptedData, false); }
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 AttributeStatement_Invalid_EncryptedAttribute_DKSaml20() { Assertion saml20Assertion = AssertionUtil.GetBasicAssertion(); List <StatementAbstract> statements = new List <StatementAbstract>(saml20Assertion.Items); AttributeStatement sas = GetAttributeStatement(statements); List <object> attributes = new List <object>(sas.Items); EncryptedElement ee = new EncryptedElement(); ee.encryptedData = new EncryptedData(); ee.encryptedData.Type = Saml20Constants.XENC + "Element"; attributes.Add(ee); sas.Items = attributes.ToArray(); saml20Assertion.Items = statements.ToArray(); XmlDocument doc = AssertionUtil.ConvertAssertion(saml20Assertion); new Saml20Assertion(doc.DocumentElement, null, false); }
public void TestSigning_02() { XmlDocument token = AssertionUtil.GetTestAssertion_01(); SignDocument(token); // Manipulate the #%!;er: Attempt to remove the <AudienceRestriction> from the list of conditions. XmlElement conditions = (XmlElement)token.GetElementsByTagName("Conditions", "urn:oasis:names:tc:SAML:2.0:assertion")[0]; XmlElement audienceRestriction = (XmlElement)conditions.GetElementsByTagName("AudienceRestriction", "urn:oasis:names:tc:SAML:2.0:assertion")[0]; conditions.RemoveChild(audienceRestriction); bool verified = VerifySignature(token); Assert.IsFalse(verified); }
public void Conditions_Element() { Assertion saml20Assertion = AssertionUtil.GetBasicAssertion(); Assert.IsNotNull(saml20Assertion.Conditions); List <ConditionAbstract> conditions = new List <ConditionAbstract>(saml20Assertion.Conditions.Items); int index = conditions.FindIndex(delegate(ConditionAbstract cond) { return(cond is AudienceRestriction); }); Assert.That(index != -1); conditions.RemoveAt(index); // Add another condition to avoid an empty list of conditions. conditions.Add(new OneTimeUse()); saml20Assertion.Conditions.Items = conditions; TestAssertion(saml20Assertion, "The DK-SAML 2.0 profile requires that an \"AudienceRestriction\" element is present on the saml20Assertion."); }
public void Subject_Element() { Assertion saml20Assertion = AssertionUtil.GetBasicAssertion(); Assert.IsNotNull(saml20Assertion.Subject); Assert.That(saml20Assertion.Subject.Items.Length > 0); SubjectConfirmation subjectConfirmation = (SubjectConfirmation)Array.Find(saml20Assertion.Subject.Items, delegate(object item) { return(item is SubjectConfirmation); }); Assert.IsNotNull(subjectConfirmation); string originalMethod = subjectConfirmation.Method; subjectConfirmation.Method = "IllegalMethod"; TestAssertion(saml20Assertion, "SubjectConfirmation element has Method attribute which is not a wellformed absolute uri."); // Try a valid url. subjectConfirmation.Method = "http://example.com"; TestAssertion(saml20Assertion, "The DK-SAML 2.0 Profile requires that a bearer \"SubjectConfirmation\" element is present."); // Restore valid settings... And verify that it is restored. subjectConfirmation.Method = originalMethod; TestAssertion(saml20Assertion, null); // Now, start messing with the <SubjectConfirmationData> element. subjectConfirmation.SubjectConfirmationData.NotOnOrAfter = null; TestAssertion(saml20Assertion, "The DK-SAML 2.0 Profile requires that the \"SubjectConfirmationData\" element contains the \"NotOnOrAfter\" attribute."); subjectConfirmation.SubjectConfirmationData.NotOnOrAfter = DateTime.UtcNow; subjectConfirmation.SubjectConfirmationData.NotBefore = DateTime.UtcNow.Subtract(new TimeSpan(5, 0, 0, 0)); TestAssertion(saml20Assertion, "The DK-SAML 2.0 Profile disallows the use of the \"NotBefore\" attribute of the \"SubjectConfirmationData\" element."); subjectConfirmation.SubjectConfirmationData.NotBefore = null; string originalRecipient = subjectConfirmation.SubjectConfirmationData.Recipient; subjectConfirmation.SubjectConfirmationData.Recipient = null; TestAssertion(saml20Assertion, "The DK-SAML 2.0 Profile requires that the \"SubjectConfirmationData\" element contains the \"Recipient\" attribute."); subjectConfirmation.SubjectConfirmationData.Recipient = originalRecipient; saml20Assertion.Subject = null; TestAssertion(saml20Assertion, "AuthnStatement, AuthzDecisionStatement and AttributeStatement require a subject."); }
public void AttributeStatement_Invalid_Statementtype() { Assertion saml20Assertion = AssertionUtil.GetBasicAssertion(); AuthzDecisionStatement authzDecisionStatement = new AuthzDecisionStatement(); authzDecisionStatement.Decision = DecisionType.Permit; authzDecisionStatement.Resource = "http://safewhere.net"; authzDecisionStatement.Action = new dk.nita.saml20.Schema.Core.Action[] { new dk.nita.saml20.Schema.Core.Action() }; authzDecisionStatement.Action[0].Namespace = "http://actionns.com"; authzDecisionStatement.Action[0].Value = "value"; List <StatementAbstract> statements = new List <StatementAbstract>(saml20Assertion.Items); statements.Add(authzDecisionStatement); saml20Assertion.Items = statements.ToArray(); new Saml20Assertion(AssertionUtil.ConvertAssertion(saml20Assertion).DocumentElement, null, false); }
public void Issuer_Element_QuirksMode() { Assertion saml20Assertion = AssertionUtil.GetBasicAssertion(); Assert.IsNotNull(saml20Assertion.Issuer); saml20Assertion.Issuer = new NameID(); saml20Assertion.Issuer.Value = "http://safewhere.net"; saml20Assertion.Issuer.Format = "http://example.com"; DKSaml20AssertionValidator quirksModeValidator = new DKSaml20AssertionValidator(AssertionUtil.GetAudiences(), true); try { quirksModeValidator.ValidateAssertion(saml20Assertion); } catch (Exception e) { Assert.That(false, "The above validation should not fail in quirksMode: " + e.ToString()); } }
public void AttributeStatement_Element() { Predicate <StatementAbstract> findAttributeStatement = delegate(StatementAbstract stmnt) { return(stmnt is AttributeStatement); }; Assertion saml20Assertion = AssertionUtil.GetBasicAssertion(); AttributeStatement attributeStatement = (AttributeStatement)Array.Find(saml20Assertion.Items, findAttributeStatement); // Add an encrypted attribute. EncryptedElement encAtt = new EncryptedElement(); encAtt.encryptedData = new EncryptedData(); encAtt.encryptedData.CipherData = new CipherData(); encAtt.encryptedData.CipherData.Item = string.Empty; encAtt.encryptedKey = new EncryptedKey[0]; attributeStatement.Items = new object[] { encAtt }; TestAssertion(saml20Assertion, "The DK-SAML 2.0 profile does not allow encrypted attributes."); // Add an attribute with the wrong nameformat. // Attribute att = DKSaml20EmailAttribute.create("*****@*****.**"); // att.NameFormat = "http://example.com"; // attributeStatement.Items = new object[] { att }; // testAssertion(saml20Assertion, "The DK-SAML 2.0 profile requires that an attribute's \"NameFormat\" element is urn:oasis:names:tc:SAML:2.0:attrname-format:uri."); // Clear all the attributes. attributeStatement.Items = new object[0]; TestAssertion(saml20Assertion, "AttributeStatement MUST contain at least one Attribute or EncryptedAttribute"); // Remove it. saml20Assertion = AssertionUtil.GetBasicAssertion(); List <StatementAbstract> statements = new List <StatementAbstract>(saml20Assertion.Items); statements.RemoveAll(findAttributeStatement); saml20Assertion.Items = statements.ToArray(); TestAssertion(saml20Assertion, "The DK-SAML 2.0 profile requires exactly one \"AuthnStatement\" element and one \"AttributeStatement\" element."); }
public void TestRetrieveIssuer() { Saml20Assertion assertion = AssertionUtil.DeserializeToken(@"Saml20\Assertions\Saml2Assertion_01", false); Assert.AreEqual("TokenService/Safewhere", assertion.Issuer); }
public DKSAML20ProfileValidationTest() { _validator = new DKSaml20AssertionValidator(AssertionUtil.GetAudiences(), false); }
/// <summary> /// Loads an assertion and tries to deserialize it using the <code>Assertion</code> class. /// </summary> public static Saml20Assertion DeserializeToken(string assertionFile) { FileStream fs = File.OpenRead(assertionFile); XmlDocument document = new XmlDocument(); document.PreserveWhitespace = true; document.Load(fs); fs.Close(); XmlNodeList nodes = document.DocumentElement.GetElementsByTagName("Issuer", Saml20Constants.ASSERTION); Saml20Assertion assertion = new Saml20Assertion(document.DocumentElement, AssertionUtil.GetTrustedSigners(nodes[0].Value), false); return(assertion); }
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]); } }
public void TestDKSaml20TokenVerification_04() { AssertionUtil.DeserializeToken(@"Saml20\Assertions\EvilSaml2Assertion_03"); }
[Ignore] // TODO: test data needs fixing public void TestDKSaml20TokenVerification_01() { AssertionUtil.DeserializeToken(@"Saml20\Assertions\Saml2Assertion_01"); AssertionUtil.DeserializeToken(@"Saml20\Assertions\Saml2Assertion_02"); AssertionUtil.DeserializeToken(@"Saml20\Assertions\Saml2Assertion_03"); }