Skip to content

Commit

Permalink
Merge pull request Sustainsys#209 from explunit/signed-assertions-wit…
Browse files Browse the repository at this point in the history
…h-keyinfo

Add test cases for signed assertions with KeyInfo
  • Loading branch information
AndersAbel committed Mar 24, 2015
2 parents 3283524 + 42f27ec commit 49a3eb8
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 3 deletions.
6 changes: 3 additions & 3 deletions Kentor.AuthServices.TestHelpers/SignedXmlHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ public class SignedXmlHelper
(new X509SecurityToken(TestCert))
.CreateKeyIdentifierClause<X509RawDataKeyIdentifierClause>()));

public static string SignXml(string xml)
public static string SignXml(string xml, bool includeKeyInfo = false, bool preserveWhitespace = true)
{
var xmlDoc = new XmlDocument { PreserveWhitespace = true };
var xmlDoc = new XmlDocument { PreserveWhitespace = preserveWhitespace };
xmlDoc.LoadXml(xml);

xmlDoc.Sign(TestCert);
xmlDoc.Sign(TestCert, includeKeyInfo);

return xmlDoc.OuterXml;
}
Expand Down
78 changes: 78 additions & 0 deletions Kentor.AuthServices.Tests/Saml2P/Saml2ResponseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,39 @@ public void Saml2Response_GetClaims_CorrectSignedSingleAssertionInResponseMessag
a.ShouldNotThrow();
}

[TestMethod]
public void Saml2Response_GetClaims_CorrectSignedSingleAssertion_WithKeyInfo_InResponseMessage()
{
var response =
@"<saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
ID = ""Saml2Response_GetClaims_CorrectSignedSingleAssertion_WithKeyInfo_InResponseMessage"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"">
<saml2:Issuer>https://idp.example.com</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
</saml2p:Status>
{0}
</saml2p:Response>";

var assertion =
@"<saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
Version=""2.0"" ID=""_{0}""
IssueInstant=""2013-09-25T00:00:00Z"">
<saml2:Issuer>https://idp.example.com</saml2:Issuer>
<saml2:Subject>
<saml2:NameID>SomeUser</saml2:NameID>
<saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
</saml2:Subject>
<saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" />
</saml2:Assertion>";

var signedAssertion = SignedXmlHelper.SignXml(string.Format(assertion, Guid.NewGuid()), true, false);
var signedResponse = string.Format(response, signedAssertion);

Action a = () => Saml2Response.Read(signedResponse).GetClaims(Options.FromConfiguration);
a.ShouldNotThrow();
}

[TestMethod]
[Ignore]
public void Saml2Response_GetClaims_CorrectSignedMultipleAssertionInResponseMessage()
Expand Down Expand Up @@ -281,6 +314,51 @@ public void Saml2Response_GetClaims_CorrectSignedMultipleAssertionInResponseMess
a.ShouldNotThrow();
}

[TestMethod]
public void Saml2Response_GetClaims_CorrectSignedMultipleAssertion_WithKeyInfo_InResponseMessage()
{
var response =
@"<saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
ID = ""Saml2Response_GetClaims_TrueOnCorrectSignedMultipleAssertionInResponseMessage"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"">
<saml2:Issuer>https://idp.example.com</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
</saml2p:Status>
{0}
{1}
</saml2p:Response>";

var assertion1 = @"<saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
Version=""2.0"" ID=""_{0}""
IssueInstant=""2013-09-25T00:00:00Z"">
<saml2:Issuer>https://idp.example.com</saml2:Issuer>
<saml2:Subject>
<saml2:NameID>SomeUser</saml2:NameID>
<saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
</saml2:Subject>
<saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" />
</saml2:Assertion>";

var assertion2 = @"<saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
Version=""2.0"" ID=""_{0}""
IssueInstant=""2013-09-25T00:00:00Z"">
<saml2:Issuer>https://idp.example.com</saml2:Issuer>
<saml2:Subject>
<saml2:NameID>SomeUser2</saml2:NameID>
<saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
</saml2:Subject>
<saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" />
</saml2:Assertion>";

var signedAssertion1 = SignedXmlHelper.SignXml(string.Format(assertion1, Guid.NewGuid()), true, false);
var signedAssertion2 = SignedXmlHelper.SignXml(string.Format(assertion2, Guid.NewGuid()), true, false);
var signedResponse = string.Format(response, signedAssertion1, signedAssertion2);

Action a = () => Saml2Response.Read(signedResponse).GetClaims(Options.FromConfiguration);
a.ShouldNotThrow();
}

[TestMethod]
public void Saml2Response_GetClaims_ThrowsOnMultipleAssertionInUnsignedResponseMessageButNotAllSigned()
{
Expand Down
20 changes: 20 additions & 0 deletions Kentor.AuthServices/XmlDocumentExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ public static class XmlDocumentExtensions
/// <param name="cert">Certificate to use when signing.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes", MessageId = "System.Xml.XmlNode")]
public static void Sign(this XmlDocument xmlDocument, X509Certificate2 cert)
{
Sign(xmlDocument, cert, false);
}

/// <summary>
/// Sign an xml document with the supplied cert.
/// </summary>
/// <param name="xmlDocument">XmlDocument to be signed. The signature is
/// added as a node in the document, right after the Issuer node.</param>
/// <param name="cert">Certificate to use when signing.</param>
/// <param name="includeKeyInfo">Include public key in signed output.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes", MessageId = "System.Xml.XmlNode")]
public static void Sign(this XmlDocument xmlDocument, X509Certificate2 cert, bool includeKeyInfo)
{
if (xmlDocument == null)
{
Expand Down Expand Up @@ -48,6 +61,13 @@ public static void Sign(this XmlDocument xmlDocument, X509Certificate2 cert)
signedXml.AddReference(reference);
signedXml.ComputeSignature();

if (includeKeyInfo)
{
var keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(cert));
signedXml.KeyInfo = keyInfo;
}

xmlDocument.DocumentElement.InsertAfter(
xmlDocument.ImportNode(signedXml.GetXml(), true),
xmlDocument.DocumentElement["Issuer", Saml2Namespaces.Saml2Name]);
Expand Down

0 comments on commit 49a3eb8

Please sign in to comment.