Skip to content

Commit 98a74ed

Browse files
committed
Support read SPSsoDescriptor. With EntityDescriptor.ReadSPSsoDescriptor, ReadSPSsoDescriptorFromFile and ReadSPSsoDescriptorFromUrl.
1 parent ade6295 commit 98a74ed

File tree

12 files changed

+239
-121
lines changed

12 files changed

+239
-121
lines changed

src/ITfoxtec.Identity.Saml2.Mvc/ITfoxtec.Identity.Saml2.Mvc.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Support .NET Framework 4.6.2 and 4.7.2</Description>
1717
<AssemblyVersion>4.0.3.0</AssemblyVersion>
1818
<FileVersion>4.0.3.0</FileVersion>
1919
<Copyright>Copyright © 2019</Copyright>
20-
<Version>4.0.3.0</Version>
20+
<Version>4.0.3.0-beta1</Version>
2121
<SignAssembly>true</SignAssembly>
2222
<AssemblyOriginatorKeyFile>ITfoxtec.SAML2.snk</AssemblyOriginatorKeyFile>
2323
<DelaySign>false</DelaySign>

src/ITfoxtec.Identity.Saml2.MvcCore/ITfoxtec.Identity.Saml2.MvcCore.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<AssemblyVersion>4.0.3.0</AssemblyVersion>
2020
<FileVersion>4.0.3.0</FileVersion>
2121
<Copyright>Copyright © 2019</Copyright>
22-
<Version>4.0.3.0</Version>
22+
<Version>4.0.3.0-beta1</Version>
2323
<SignAssembly>true</SignAssembly>
2424
<AssemblyOriginatorKeyFile>ITfoxtec.SAML2.snk</AssemblyOriginatorKeyFile>
2525
<DelaySign>false</DelaySign>

src/ITfoxtec.Identity.Saml2/ITfoxtec.Identity.Saml2.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Tested for compliance with AD FS, Azure AD and Azure AD B2C. Furthermore, the Da
2424
<AssemblyVersion>4.0.3.0</AssemblyVersion>
2525
<FileVersion>4.0.3.0</FileVersion>
2626
<Copyright>Copyright © 2019</Copyright>
27-
<Version>4.0.3.0</Version>
27+
<Version>4.0.3.0-beta1</Version>
2828
<SignAssembly>true</SignAssembly>
2929
<AssemblyOriginatorKeyFile>ITfoxtec.SAML2.snk</AssemblyOriginatorKeyFile>
3030
<DelaySign>false</DelaySign>

src/ITfoxtec.Identity.Saml2/Schemas/Metadata/EntityDescriptor.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,28 @@ public virtual EntityDescriptor ReadIdPSsoDescriptor(string idPMetadataXml)
161161
return this;
162162
}
163163

164+
public virtual EntityDescriptor ReadSPSsoDescriptor(string spMetadataXml)
165+
{
166+
var metadataXmlDocument = spMetadataXml.ToXmlDocument();
167+
168+
if (metadataXmlDocument.DocumentElement.NamespaceURI != Saml2MetadataConstants.MetadataNamespace.OriginalString)
169+
{
170+
throw new Saml2RequestException("Not Metadata.");
171+
}
172+
173+
EntityId = metadataXmlDocument.DocumentElement.Attributes[Saml2MetadataConstants.Message.EntityId].GetValueOrNull<string>();
174+
175+
Id = metadataXmlDocument.DocumentElement.Attributes[Saml2MetadataConstants.Message.Id].GetValueOrNull<Saml2Id>();
176+
177+
var spSsoDescriptorElement = metadataXmlDocument.DocumentElement[Saml2MetadataConstants.Message.SPSsoDescriptor, Saml2MetadataConstants.MetadataNamespace.OriginalString];
178+
if (spSsoDescriptorElement != null)
179+
{
180+
SPSsoDescriptor = new SPSsoDescriptor().Read(spSsoDescriptorElement);
181+
}
182+
183+
return this;
184+
}
185+
164186
public virtual EntityDescriptor ReadIdPSsoDescriptorFromFile(string idPMetadataFile)
165187
{
166188
return ReadIdPSsoDescriptor(File.ReadAllText(idPMetadataFile));
@@ -173,5 +195,18 @@ public virtual EntityDescriptor ReadIdPSsoDescriptorFromUrl(Uri idPMetadataUrl)
173195
return ReadIdPSsoDescriptor(webClient.DownloadString(idPMetadataUrl));
174196
}
175197
}
198+
199+
public virtual EntityDescriptor ReadSPSsoDescriptorFromFile(string spMetadataFile)
200+
{
201+
return ReadSPSsoDescriptor(File.ReadAllText(spMetadataFile));
202+
}
203+
204+
public virtual EntityDescriptor ReadSPSsoDescriptorFromUrl(Uri spMetadataUrl)
205+
{
206+
using (var webClient = new WebClient())
207+
{
208+
return ReadSPSsoDescriptor(webClient.DownloadString(spMetadataUrl));
209+
}
210+
}
176211
}
177212
}

src/ITfoxtec.Identity.Saml2/Schemas/Metadata/IdPSsoDescriptor.cs

Lines changed: 4 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Security.Cryptography.X509Certificates;
4-
using System.Security.Cryptography.Xml;
53
using System.Xml;
64
using System.Xml.Linq;
75

@@ -93,86 +91,19 @@ protected internal IdPSsoDescriptor Read(XmlElement xmlElement)
9391
{
9492
WantAuthnRequestsSigned = xmlElement.Attributes[Saml2MetadataConstants.Message.WantAuthnRequestsSigned]?.Value.Equals(true.ToString(), StringComparison.InvariantCultureIgnoreCase);
9593

96-
var signingKeyDescriptorElements = xmlElement.SelectNodes($"*[local-name()='{Saml2MetadataConstants.Message.KeyDescriptor}'][contains(@use,'{Saml2MetadataConstants.KeyTypes.Signing}') or not(@use)]");
97-
if (signingKeyDescriptorElements != null)
98-
{
99-
SigningCertificates = ReadKeyDescriptorElements(signingKeyDescriptorElements);
100-
}
101-
102-
var encryptionKeyDescriptorElements = xmlElement.SelectNodes($"*[local-name()='{Saml2MetadataConstants.Message.KeyDescriptor}'][contains(@use,'{Saml2MetadataConstants.KeyTypes.Encryption}') or not(@use)]");
103-
if (encryptionKeyDescriptorElements != null)
104-
{
105-
EncryptionCertificates = ReadKeyDescriptorElements(encryptionKeyDescriptorElements);
106-
}
94+
ReadKeyDescriptors(xmlElement);
10795

10896
var singleSignOnServiceElements = xmlElement.SelectNodes($"*[local-name()='{Saml2MetadataConstants.Message.SingleSignOnService}']");
10997
if (singleSignOnServiceElements != null)
11098
{
11199
SingleSignOnServices = ReadServices<SingleSignOnService>(singleSignOnServiceElements);
112100
}
113101

114-
var singleLogoutServiceElements = xmlElement.SelectNodes($"*[local-name()='{Saml2MetadataConstants.Message.SingleLogoutService}']");
115-
if (singleLogoutServiceElements != null)
116-
{
117-
SingleLogoutServices = ReadServices<SingleLogoutService>(singleLogoutServiceElements);
118-
}
102+
ReadSingleLogoutService(xmlElement);
119103

120-
var nameIDFormatElements = xmlElement.SelectNodes($"*[local-name()='{Saml2MetadataConstants.Message.NameIDFormat}']");
121-
if (nameIDFormatElements != null)
122-
{
123-
NameIDFormats = ReadNameIDFormatElements(nameIDFormatElements);
124-
}
104+
ReadNameIDFormat(xmlElement);
125105

126106
return this;
127-
}
128-
129-
private IEnumerable<X509Certificate2> ReadKeyDescriptorElements(XmlNodeList keyDescriptorElements)
130-
{
131-
foreach (XmlElement keyDescriptorElement in keyDescriptorElements)
132-
{
133-
var keyInfoElement = keyDescriptorElement.SelectSingleNode($"*[local-name()='{Saml2MetadataConstants.Message.KeyInfo}']") as XmlElement;
134-
if (keyInfoElement != null)
135-
{
136-
var keyInfo = new KeyInfo();
137-
keyInfo.LoadXml(keyInfoElement);
138-
var keyInfoEnumerator = keyInfo.GetEnumerator();
139-
while (keyInfoEnumerator.MoveNext())
140-
{
141-
var keyInfoX509Data = keyInfoEnumerator.Current as KeyInfoX509Data;
142-
if (keyInfoX509Data != null)
143-
{
144-
foreach (var certificate in keyInfoX509Data.Certificates)
145-
{
146-
if (certificate is X509Certificate2)
147-
{
148-
yield return certificate as X509Certificate2;
149-
}
150-
}
151-
}
152-
}
153-
}
154-
}
155-
}
156-
157-
private IEnumerable<Uri> ReadNameIDFormatElements(XmlNodeList nameIDFormatElements)
158-
{
159-
foreach (XmlNode nameIDFormatElement in nameIDFormatElements)
160-
{
161-
yield return new Uri(nameIDFormatElement.InnerText);
162-
}
163-
}
164-
165-
private IEnumerable<T> ReadServices<T>(XmlNodeList singleLogoutServiceElements) where T : EndpointType, new()
166-
{
167-
foreach (XmlNode singleLogoutServiceElement in singleLogoutServiceElements)
168-
{
169-
yield return new T
170-
{
171-
Binding = singleLogoutServiceElement.Attributes[Saml2MetadataConstants.Message.Binding].GetValueOrNull<Uri>(),
172-
Location = singleLogoutServiceElement.Attributes[Saml2MetadataConstants.Message.Location].GetValueOrNull<Uri>(),
173-
ResponseLocation = singleLogoutServiceElement.Attributes[Saml2MetadataConstants.Message.ResponseLocation].GetValueOrNull<Uri>()
174-
};
175-
}
176-
}
107+
}
177108
}
178109
}

src/ITfoxtec.Identity.Saml2/Schemas/Metadata/SPSsoDescriptor.cs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Security.Cryptography.X509Certificates;
4-
using System.Security.Cryptography.Xml;
3+
using System.Xml;
54
using System.Xml.Linq;
65

76
namespace ITfoxtec.Identity.Saml2.Schemas.Metadata
@@ -118,5 +117,39 @@ protected IEnumerable<XObject> GetXContent()
118117
}
119118
}
120119
}
120+
121+
122+
protected internal SPSsoDescriptor Read(XmlElement xmlElement)
123+
{
124+
AuthnRequestsSigned = xmlElement.Attributes[Saml2MetadataConstants.Message.AuthnRequestsSigned]?.Value.Equals(true.ToString(), StringComparison.InvariantCultureIgnoreCase);
125+
126+
WantAssertionsSigned = xmlElement.Attributes[Saml2MetadataConstants.Message.WantAssertionsSigned]?.Value.Equals(true.ToString(), StringComparison.InvariantCultureIgnoreCase);
127+
128+
ReadKeyDescriptors(xmlElement);
129+
130+
var assertionConsumerServicesElements = xmlElement.SelectNodes($"*[local-name()='{Saml2MetadataConstants.Message.AssertionConsumerService}']");
131+
if (assertionConsumerServicesElements != null)
132+
{
133+
AssertionConsumerServices = ReadAcsService(assertionConsumerServicesElements);
134+
}
135+
136+
ReadSingleLogoutService(xmlElement);
137+
138+
ReadNameIDFormat(xmlElement);
139+
140+
return this;
141+
}
142+
143+
protected IEnumerable<AssertionConsumerService> ReadAcsService(XmlNodeList acsElements)
144+
{
145+
foreach (XmlNode singleLogoutServiceElement in acsElements)
146+
{
147+
yield return new AssertionConsumerService
148+
{
149+
Binding = singleLogoutServiceElement.Attributes[Saml2MetadataConstants.Message.Binding].GetValueOrNull<Uri>(),
150+
Location = singleLogoutServiceElement.Attributes[Saml2MetadataConstants.Message.Location].GetValueOrNull<Uri>(),
151+
};
152+
}
153+
}
121154
}
122155
}

src/ITfoxtec.Identity.Saml2/Schemas/Metadata/SsoDescriptorType.cs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Security.Cryptography.X509Certificates;
44
using System.Security.Cryptography.Xml;
5+
using System.Xml;
56
using System.Xml.Linq;
67

78
namespace ITfoxtec.Identity.Saml2.Schemas.Metadata
@@ -63,5 +64,87 @@ protected XObject KeyDescriptor(X509Certificate2 certificate, string keyType)
6364
new XAttribute(Saml2MetadataConstants.Message.Use, keyType),
6465
XElement.Parse(keyinfo.GetXml().OuterXml));
6566
}
67+
68+
protected void ReadKeyDescriptors(XmlElement xmlElement)
69+
{
70+
var signingKeyDescriptorElements = xmlElement.SelectNodes($"*[local-name()='{Saml2MetadataConstants.Message.KeyDescriptor}'][contains(@use,'{Saml2MetadataConstants.KeyTypes.Signing}') or not(@use)]");
71+
if (signingKeyDescriptorElements != null)
72+
{
73+
SigningCertificates = ReadKeyDescriptorElements(signingKeyDescriptorElements);
74+
}
75+
76+
var encryptionKeyDescriptorElements = xmlElement.SelectNodes($"*[local-name()='{Saml2MetadataConstants.Message.KeyDescriptor}'][contains(@use,'{Saml2MetadataConstants.KeyTypes.Encryption}') or not(@use)]");
77+
if (encryptionKeyDescriptorElements != null)
78+
{
79+
EncryptionCertificates = ReadKeyDescriptorElements(encryptionKeyDescriptorElements);
80+
}
81+
}
82+
83+
protected void ReadSingleLogoutService(XmlElement xmlElement)
84+
{
85+
var singleLogoutServiceElements = xmlElement.SelectNodes($"*[local-name()='{Saml2MetadataConstants.Message.SingleLogoutService}']");
86+
if (singleLogoutServiceElements != null)
87+
{
88+
SingleLogoutServices = ReadServices<SingleLogoutService>(singleLogoutServiceElements);
89+
}
90+
}
91+
92+
protected void ReadNameIDFormat(XmlElement xmlElement)
93+
{
94+
var nameIDFormatElements = xmlElement.SelectNodes($"*[local-name()='{Saml2MetadataConstants.Message.NameIDFormat}']");
95+
if (nameIDFormatElements != null)
96+
{
97+
NameIDFormats = ReadNameIDFormatElements(nameIDFormatElements);
98+
}
99+
}
100+
101+
protected IEnumerable<Uri> ReadNameIDFormatElements(XmlNodeList nameIDFormatElements)
102+
{
103+
foreach (XmlNode nameIDFormatElement in nameIDFormatElements)
104+
{
105+
yield return new Uri(nameIDFormatElement.InnerText);
106+
}
107+
}
108+
109+
protected IEnumerable<X509Certificate2> ReadKeyDescriptorElements(XmlNodeList keyDescriptorElements)
110+
{
111+
foreach (XmlElement keyDescriptorElement in keyDescriptorElements)
112+
{
113+
var keyInfoElement = keyDescriptorElement.SelectSingleNode($"*[local-name()='{Saml2MetadataConstants.Message.KeyInfo}']") as XmlElement;
114+
if (keyInfoElement != null)
115+
{
116+
var keyInfo = new KeyInfo();
117+
keyInfo.LoadXml(keyInfoElement);
118+
var keyInfoEnumerator = keyInfo.GetEnumerator();
119+
while (keyInfoEnumerator.MoveNext())
120+
{
121+
var keyInfoX509Data = keyInfoEnumerator.Current as KeyInfoX509Data;
122+
if (keyInfoX509Data != null)
123+
{
124+
foreach (var certificate in keyInfoX509Data.Certificates)
125+
{
126+
if (certificate is X509Certificate2)
127+
{
128+
yield return certificate as X509Certificate2;
129+
}
130+
}
131+
}
132+
}
133+
}
134+
}
135+
}
136+
137+
protected IEnumerable<T> ReadServices<T>(XmlNodeList serviceElements) where T : EndpointType, new()
138+
{
139+
foreach (XmlNode serviceElement in serviceElements)
140+
{
141+
yield return new T
142+
{
143+
Binding = serviceElement.Attributes[Saml2MetadataConstants.Message.Binding].GetValueOrNull<Uri>(),
144+
Location = serviceElement.Attributes[Saml2MetadataConstants.Message.Location].GetValueOrNull<Uri>(),
145+
ResponseLocation = serviceElement.Attributes[Saml2MetadataConstants.Message.ResponseLocation].GetValueOrNull<Uri>()
146+
};
147+
}
148+
}
66149
}
67150
}

0 commit comments

Comments
 (0)