Skip to content

Commit 7f91701

Browse files
committed
Relaxed audience restriction. Real world tests show that some IdPs do not send this. DUH
1 parent 3fe8d26 commit 7f91701

2 files changed

Lines changed: 63 additions & 1 deletion

File tree

AspNetSaml.Tests/UnitTests.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,43 @@ public void TestSamlSignoutResponseValidator()
9090
Assert.IsTrue(samlresp.GetLogoutStatus() == "Success");
9191
}
9292

93+
[TestMethod]
94+
public void TestAudienceValidationAllowsEmptyAudienceRestriction()
95+
{
96+
var samlresp = new TestResponse(GetTestCertificate());
97+
98+
samlresp.LoadXml(@"<samlp:Response xmlns:samlp=""urn:oasis:names:tc:SAML:2.0:protocol"" xmlns:saml=""urn:oasis:names:tc:SAML:2.0:assertion"">
99+
<saml:Assertion>
100+
<saml:Conditions>
101+
<saml:AudienceRestriction>
102+
<saml:Audience />
103+
</saml:AudienceRestriction>
104+
</saml:Conditions>
105+
</saml:Assertion>
106+
</samlp:Response>");
107+
108+
Assert.IsTrue(samlresp.IsAudienceValid("WebApp3"));
109+
}
110+
111+
[TestMethod]
112+
public void TestAudienceValidationRejectsNonMatchingAudience()
113+
{
114+
var samlresp = new TestResponse(GetTestCertificate());
115+
116+
samlresp.LoadXml(@"<samlp:Response xmlns:samlp=""urn:oasis:names:tc:SAML:2.0:protocol"" xmlns:saml=""urn:oasis:names:tc:SAML:2.0:assertion"">
117+
<saml:Assertion>
118+
<saml:Conditions>
119+
<saml:AudienceRestriction>
120+
<saml:Audience>OtherApp</saml:Audience>
121+
<saml:Audience />
122+
</saml:AudienceRestriction>
123+
</saml:Conditions>
124+
</saml:Assertion>
125+
</samlp:Response>");
126+
127+
Assert.IsFalse(samlresp.IsAudienceValid("WebApp3"));
128+
}
129+
93130
[TestMethod]
94131
public void TestSamlResponseValidatorAdvanced()
95132
{
@@ -186,6 +223,23 @@ private static byte[] StringToByteArray(string st)
186223
return bytes;
187224
}
188225

226+
private static string GetTestCertificate()
227+
{
228+
return @"-----BEGIN CERTIFICATE-----
229+
MIICajCCAdOgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBSMQswCQYDVQQGEwJ1czETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMT25lbG9naW4gSW5jMRcwFQYDVQQDDA5zcC5leGFtcGxlLmNvbTAeFw0xNDA3MTcxNDEyNTZaFw0xNTA3MTcxNDEyNTZaMFIxCzAJBgNVBAYTAnVzMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxPbmVsb2dpbiBJbmMxFzAVBgNVBAMMDnNwLmV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZx+ON4IUoIWxgukTb1tOiX3bMYzYQiwWPUNMp+Fq82xoNogso2bykZG0yiJm5o8zv/sd6pGouayMgkx/2FSOdc36T0jGbCHuRSbtia0PEzNIRtmViMrt3AeoWBidRXmZsxCNLwgIV6dn2WpuE5Az0bHgpZnQxTKFek0BMKU/d8wIDAQABo1AwTjAdBgNVHQ4EFgQUGHxYqZYyX7cTxKVODVgZwSTdCnwwHwYDVR0jBBgwFoAUGHxYqZYyX7cTxKVODVgZwSTdCnwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOBgQByFOl+hMFICbd3DJfnp2Rgd/dqttsZG/tyhILWvErbio/DEe98mXpowhTkC04ENprOyXi7ZbUqiicF89uAGyt1oqgTUCD1VsLahqIcmrzgumNyTwLGWo17WDAa1/usDhetWAMhgzF/Cnf5ek0nK00m0YZGyc4LzgD0CROMASTWNg==
230+
-----END CERTIFICATE-----";
231+
}
232+
233+
private class TestResponse : Saml.Response
234+
{
235+
public TestResponse(string certificateStr) : base(certificateStr) { }
236+
237+
public bool IsAudienceValid(string audienceEntityId)
238+
{
239+
return ValidateAudience(audienceEntityId);
240+
}
241+
}
242+
189243
[TestMethod]
190244
public void TestIdpLogoutRequest()
191245
{

AspNetSaml/Saml.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,15 @@ protected bool ValidateAudience(string audienceEntityId)
156156
return false;
157157

158158
XmlNodeList nodes = _xmlDoc.SelectNodes("/samlp:Response/saml:Assertion[1]/saml:Conditions/saml:AudienceRestriction/saml:Audience", _xmlNameSpaceManager);
159-
return nodes != null && nodes.Cast<XmlNode>().Any(x => string.Equals(x.InnerText, audienceEntityId, StringComparison.Ordinal));
159+
if (nodes == null) return true;
160+
161+
var audiences = nodes.Cast<XmlNode>()
162+
.Select(x => x.InnerText)
163+
.Where(x => !string.IsNullOrWhiteSpace(x))
164+
.ToList();
165+
166+
return audiences.Count == 0 // no audience restriction from IdP, so we consider it valid. Tested with real IdP's like "OneLogin" etc. They just don't send it. Duh.
167+
|| audiences.Any(x => string.Equals(x, audienceEntityId, StringComparison.Ordinal));
160168
}
161169

162170
/// <summary>

0 commit comments

Comments
 (0)