Skip to content

Commit

Permalink
Fix xml signature verification and update to .net 9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniele Giallonardo committed Jan 19, 2025
1 parent 304c7f7 commit 672419c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 96 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: 7.x
dotnet-version: 9.x
- name: Restore dependencies
run: dotnet restore
working-directory: CIE.AspNetCore.Authentication
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net7.0;net6.0;net5.0</TargetFrameworks>
<TargetFrameworks>net9.0;net8.0;net7.0;net6.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<Description>AspNetCore Remote Authenticator for CIE</Description>
<Authors>Daniele Giallonardo, Stefano Mostarda</Authors>
Expand All @@ -12,42 +12,42 @@
<PackageProjectUrl>https://github.com/italia/cie-aspnetcore</PackageProjectUrl>
<PackageIcon>cie-nuget.png</PackageIcon>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageVersion>2.0.4</PackageVersion>
<Version>2.0.4</Version>
<AssemblyVersion>2.0.4</AssemblyVersion>
<FileVersion>2.0.4</FileVersion>
<InformationalVersion>2.0.4</InformationalVersion>
<PackageVersion>2.0.5</PackageVersion>
<Version>2.0.5</Version>
<AssemblyVersion>2.0.5</AssemblyVersion>
<FileVersion>2.0.5</FileVersion>
<InformationalVersion>2.0.5</InformationalVersion>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/italia/cie-aspnetcore</RepositoryUrl>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Razor" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.21" />
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.1" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.1" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net6.0'">
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="7.0.1" />
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.12" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.2" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net7.0' ">
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.10" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.12" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.2" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net6.0' ">
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.21" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net5.0' ">
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="5.0.17" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="5.0.0" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using CIE.AspNetCore.Authentication.Resources;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.Xml;
using System.Xml.Serialization;

namespace CIE.AspNetCore.Authentication.Helpers
{
Expand Down Expand Up @@ -36,7 +34,7 @@ internal static XmlElement SignXMLDoc(XmlDocument doc,

try
{
privateKey = certificate.PrivateKey;
privateKey = certificate.GetRSAPrivateKey();
}
catch (Exception ex)
{
Expand Down Expand Up @@ -80,11 +78,9 @@ internal static bool VerifySignature(XmlDocument signedDocument, Saml.IdP.Entity

try
{
SignedXml signedXml = new SignedXml(signedDocument);

if (xmlMetadata is not null)
{
bool validated = false;
var validated = false;
var idpSSODescriptor = xmlMetadata.Items.FirstOrDefault(i => i is Saml.IdP.IDPSSODescriptorType) as Saml.IdP.IDPSSODescriptorType;
if (idpSSODescriptor is not null)
{
Expand All @@ -96,14 +92,7 @@ internal static bool VerifySignature(XmlDocument signedDocument, Saml.IdP.Entity
var x509Cert = keyData.Items.FirstOrDefault(i => i is byte[]) as byte[];
if (x509Cert is not null)
{
var publicMetadataCert = new X509Certificate2(x509Cert);
XmlNodeList nodeList = (signedDocument.GetElementsByTagName("ds:Signature")?.Count > 1) ?
signedDocument.GetElementsByTagName("ds:Signature") :
(signedDocument.GetElementsByTagName("ns2:Signature")?.Count > 1) ?
signedDocument.GetElementsByTagName("ns2:Signature") :
signedDocument.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
validated |= signedXml.CheckSignature(publicMetadataCert, true);
validated |= VerifyAllSignatures(signedDocument, new X509Certificate2(x509Cert));
}
}
}
Expand All @@ -112,11 +101,7 @@ internal static bool VerifySignature(XmlDocument signedDocument, Saml.IdP.Entity
}
else
{
XmlNodeList nodeList = (signedDocument.GetElementsByTagName("ds:Signature")?.Count > 0) ?
signedDocument.GetElementsByTagName("ds:Signature") :
signedDocument.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
return signedXml.CheckSignature();
return VerifyAllSignatures(signedDocument);
}
}
catch (Exception)
Expand All @@ -125,64 +110,26 @@ internal static bool VerifySignature(XmlDocument signedDocument, Saml.IdP.Entity
}
}

private static readonly ConcurrentDictionary<Type, XmlSerializer> serializers = new ConcurrentDictionary<Type, XmlSerializer>();
/// <summary>
/// Serializes to XML document.
/// </summary>
/// <param name="o">The o.</param>
/// <returns></returns>
public static XmlDocument SerializeToXmlDoc(this object o)
private static bool VerifyAllSignatures(XmlDocument signedDocument, X509Certificate2? publicMetadataCert = null)

Check warning on line 113 in CIE.AspNetCore.Authentication/CIE.AspNetCore.Authentication/Helpers/XmlHelpers.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 113 in CIE.AspNetCore.Authentication/CIE.AspNetCore.Authentication/Helpers/XmlHelpers.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 113 in CIE.AspNetCore.Authentication/CIE.AspNetCore.Authentication/Helpers/XmlHelpers.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 113 in CIE.AspNetCore.Authentication/CIE.AspNetCore.Authentication/Helpers/XmlHelpers.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 113 in CIE.AspNetCore.Authentication/CIE.AspNetCore.Authentication/Helpers/XmlHelpers.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 113 in CIE.AspNetCore.Authentication/CIE.AspNetCore.Authentication/Helpers/XmlHelpers.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
{
XmlDocument doc = new XmlDocument() { PreserveWhitespace = true };
bool internalResult = true;

XmlNodeList signatureNodes = signedDocument.GetElementsByTagName("Signature", SignedXml.XmlDsigNamespaceUrl);

using XmlWriter writer = doc.CreateNavigator().AppendChild();
if (!serializers.ContainsKey(o.GetType()))
if (signatureNodes.Count == 0)
{
var serializer = new XmlSerializer(o.GetType());
serializers.AddOrUpdate(o.GetType(), serializer, (key, value) => serializer);
return false;
}
serializers[o.GetType()].Serialize(writer, o);

return doc;
}

public static XmlElement SerializeInternalExtensionToXmlElement(object o, string namespacePrefix, string xmlNamespace)
{
XmlDocument doc = SerializeExtensionToXmlElementInternal(o, namespacePrefix, xmlNamespace);

return doc.DocumentElement.FirstChild as XmlElement;
}

public static XmlElement SerializeExtensionToXmlElement(object o, string namespacePrefix, string xmlNamespace)
{
XmlDocument doc = SerializeExtensionToXmlElementInternal(o, namespacePrefix, xmlNamespace);

return doc.DocumentElement;
}

private static XmlDocument SerializeExtensionToXmlElementInternal(object o, string namespacePrefix, string xmlNamespace)
{
XmlDocument doc = new XmlDocument();

using (XmlWriter writer = doc.CreateNavigator().AppendChild())
foreach (var signatureNode in signatureNodes)
{
var ns = new XmlSerializerNamespaces();
ns.Add(namespacePrefix, xmlNamespace);
new XmlSerializer(o.GetType()).Serialize(writer, o, ns);
SignedXml signedXml = new(signedDocument);
signedXml.LoadXml((XmlElement)signatureNode);
internalResult &= publicMetadataCert is null
? signedXml.CheckSignature()
: signedXml.CheckSignature(publicMetadataCert, true);
}

return doc;
}

public static XmlElement GetXmlElement(string prefix, string prefixNamespace, string tag, string value = null)
{
XmlDocument doc = new XmlDocument();

XmlElement elem = doc.CreateElement(prefix, tag, prefixNamespace);
if(!string.IsNullOrEmpty(value))
elem.InnerText = value;

return elem;
return internalResult;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
<UserSecretsId>b637b4cd-be76-4dc7-851e-b721746073a1</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="7.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 672419c

Please sign in to comment.