Skip to content

Commit

Permalink
Some work on SamlResponse deserializing
Browse files Browse the repository at this point in the history
  • Loading branch information
AndersAbel committed Oct 15, 2023
1 parent fe62775 commit 0e98e1f
Show file tree
Hide file tree
Showing 32 changed files with 436 additions and 142 deletions.
4 changes: 2 additions & 2 deletions src/Sustainsys.Saml2.AspNetCore/Saml2Handler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync

var samlMessage = await binding.UnbindAsync(Context.Request, str => Task.FromResult<Saml2Entity>(Options.IdentityProvider!));

var source = XmlHelpers.GetXmlTraverser(samlMessage.Data.Xml);
var source = XmlHelpers.GetXmlTraverser(samlMessage.Xml);
var serializer = GetService(sr => sr.GetSamlpSerializer);
var samlResponse = serializer.ReadSamlResponse(source);

Expand All @@ -88,7 +88,7 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties prop
var authnRequest = new AuthnRequest()
{
Issuer = Options.EntityId,
IssueInstant = Clock.UtcNow,
IssueInstant = Clock.UtcNow.DateTime,
AssertionConsumerServiceUrl = BuildRedirectUri(Options.CallbackPath)
};

Expand Down
4 changes: 2 additions & 2 deletions src/Sustainsys.Saml2/Bindings/FrontChannelBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public interface IFrontChannelBinding
/// <param name="httpRequest">HttpRequest to unbind from</param>
/// <param name="getSaml2Entity">Func that returns a Saml2 entity from an entity id</param>
/// <returns></returns>
Task<TrustedData<Saml2Message>> UnbindAsync(HttpRequest httpRequest,
Task<Saml2Message> UnbindAsync(HttpRequest httpRequest,
Func<string, Task<Saml2Entity>> getSaml2Entity);

/// <summary>
Expand Down Expand Up @@ -83,7 +83,7 @@ public Task BindAsync(HttpResponse httpResponse, Saml2Message message)
protected abstract Task DoBindAsync(HttpResponse httpResponse, Saml2Message message);

/// <inheritdoc />
public abstract Task<TrustedData<Saml2Message>> UnbindAsync(
public abstract Task<Saml2Message> UnbindAsync(
HttpRequest httpRequest,
Func<string, Task<Saml2Entity>> getSaml2Entity);
}
18 changes: 8 additions & 10 deletions src/Sustainsys.Saml2/Bindings/HttpPostBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public override bool CanUnbind(HttpRequest httpRequest)
k => k == Constants.SamlRequest || k == Constants.SamlResponse);

/// <inheritdoc/>
public override Task<TrustedData<Saml2Message>> UnbindAsync(
public override Task<Saml2Message> UnbindAsync(
HttpRequest httpRequest,
Func<string, Task<Saml2Entity>> getSaml2Entity)
{
Expand Down Expand Up @@ -61,15 +61,13 @@ public override Task<TrustedData<Saml2Message>> UnbindAsync(
xd.LoadXml(Encoding.UTF8.GetString(Convert.FromBase64String(httpRequest.Form[name].Single()
?? throw new InvalidOperationException("No form content found"))));

return Task.FromResult(new TrustedData<Saml2Message>(
TrustLevel.None,
new Saml2Message
{
Destination = httpRequest.PathBase + httpRequest.Path,
Name = name,
RelayState = httpRequest.Form[Constants.RelayState].SingleOrDefault(),
Xml = xd.DocumentElement!
}));
return Task.FromResult(new Saml2Message
{
Destination = httpRequest.PathBase + httpRequest.Path,
Name = name,
RelayState = httpRequest.Form[Constants.RelayState].SingleOrDefault(),
Xml = xd.DocumentElement!
});
}

/// <inheritdoc/>
Expand Down
2 changes: 1 addition & 1 deletion src/Sustainsys.Saml2/Bindings/HttpRedirectBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public Saml2Message UnBindAsync(
=> throw new NotImplementedException();

/// <inheritdoc/>
public override Task<TrustedData<Saml2Message>> UnbindAsync(
public override Task<Saml2Message> UnbindAsync(
HttpRequest httpRequest,
Func<string, Task<Saml2Entity>> getSaml2Entity) => throw new NotImplementedException();

Expand Down
15 changes: 14 additions & 1 deletion src/Sustainsys.Saml2/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Sustainsys.Saml2.Xml;
using Sustainsys.Saml2.Samlp;
using Sustainsys.Saml2.Xml;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -68,4 +69,16 @@ public static class BindingUris
/// </summary>
public const string SOAP = "urn:oasis:names:tc:SAML:2.0:bindings:SOAP";
}


/// <summary>
/// Standard status code URIs
/// </summary>
public static class StatusCodes
{
/// <summary>
/// Failed because of the requester, i.e. invalid request.
/// </summary>
public const string Requester = "urn:oasis:names:tc:SAML:2.0:status:Requester";
}
}
5 changes: 5 additions & 0 deletions src/Sustainsys.Saml2/Metadata/Elements/EntityDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,9 @@ public class EntityDescriptor
/// Role Descriptors.
/// </summary>
public List<RoleDescriptor> RoleDescriptors { get; } = new();

/// <summary>
/// Trustlevel, set from validation of the signature, if there was one.
/// </summary>
public TrustLevel TrustLevel { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected virtual IndexedEndpoint ReadIndexedEndpoint(XmlTraverser source)
{
var result = new IndexedEndpoint()
{
Index = source.GetRequiredIntAttribute(AttributeNames.index) ?? 0,
Index = source.GetRequiredIntAttribute(AttributeNames.index),
IsDefault = source.GetBoolAttribute(AttributeNames.isDefault) ?? false
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,21 @@ partial class MetadataSerializer
/// Read an EntityDescriptor
/// </summary>
/// <returns>EntityDescriptor</returns>
public virtual TrustedData<EntityDescriptor> ReadEntityDescriptor(XmlTraverser source)
public virtual EntityDescriptor ReadEntityDescriptor(XmlTraverser source)
{
var entityDescriptor = CreateEntityDescriptor();

TrustLevel trustLevel = TrustLevel.None;

if (source.EnsureName(NamespaceUri, ElementNames.EntityDescriptor))
{
ReadAttributes(source, entityDescriptor);
trustLevel = ReadElements(source.GetChildren(), entityDescriptor);
ReadElements(source.GetChildren(), entityDescriptor);
}

source.MoveNext(true);

ThrowOnErrors(source);

return new(trustLevel,entityDescriptor);
return entityDescriptor;
}

/// <summary>
Expand All @@ -53,14 +51,14 @@ protected virtual void ReadAttributes(XmlTraverser source, EntityDescriptor enti
/// </summary>
/// <param name="source">Source data</param>
/// <param name="entityDescriptor">Entity Descriptor to populate</param>
/// <returns>Trustlevel based on signature</returns>
protected virtual TrustLevel ReadElements(XmlTraverser source, EntityDescriptor entityDescriptor)
protected virtual void ReadElements(XmlTraverser source, EntityDescriptor entityDescriptor)
{
source.MoveNext();

if (source.ReadAndValidateOptionalSignature(
TrustedSigningKeys, AllowedHashAlgorithms, out var trustLevel))
{
entityDescriptor.TrustLevel = trustLevel;
source.MoveNext();
}

Expand Down Expand Up @@ -101,7 +99,5 @@ protected virtual TrustLevel ReadElements(XmlTraverser source, EntityDescriptor
wasRoleDescriptor = false;
}
} while (wasRoleDescriptor && source.MoveNext(true));

return trustLevel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ partial class MetadataSerializer
/// <summary>
/// Create an IDPSSODescriptor instance.
/// </summary>
protected virtual IDPSSODescriptor CreateIDPSSODescriptor => new();
protected virtual IDPSSODescriptor CreateIDPSSODescriptor() => new();

/// <summary>
/// Read the current node as an IDPSSODescriptor
Expand All @@ -18,7 +18,7 @@ partial class MetadataSerializer
/// <returns></returns>
protected virtual IDPSSODescriptor ReadIDPSSODescriptor(XmlTraverser source)
{
var result = new IDPSSODescriptor();
var result = CreateIDPSSODescriptor();

ReadAttributes(source, result);

Expand Down
30 changes: 30 additions & 0 deletions src/Sustainsys.Saml2/Samlp/Attributes/AttributeNames.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace Sustainsys.Saml2.Samlp.Attributes;

/// <summary>
/// Name of Samlp attributes
/// </summary>
/// <remarks>The naming of the constants are deriberately not following
/// casing convention in order to be exactly the same as the contents.
/// </remarks>
public class AttributeNames
{
/// <summary>
/// ID attribute
/// </summary>
public const string ID = nameof(ID);

/// <summary>
/// IssueInstant
/// </summary>
public const string IssueInstant = nameof(IssueInstant);

/// <summary>
/// Version
/// </summary>
public const string Version = nameof(Version);

/// <summary>
/// Value
/// </summary>
public const string Value = nameof(Value);
}
23 changes: 23 additions & 0 deletions src/Sustainsys.Saml2/Samlp/Elements/ElementNames.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Sustainsys.Saml2.Samlp.Elements;

/// <summary>
/// Name of Samlp elements
/// </summary>
public static class ElementNames
{
/// <summary>
/// Response
/// </summary>
public const string Response = nameof(Response);

/// <summary>
/// Status
/// </summary>
public const string Status = nameof(Status);


/// <summary>
/// StatusCode
/// </summary>
public const string StatusCode = nameof(StatusCode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.Text;
using System.Threading.Tasks;

namespace Sustainsys.Saml2.Samlp;
namespace Sustainsys.Saml2.Samlp.Elements;

/// <summary>
/// Extensions
Expand Down
23 changes: 23 additions & 0 deletions src/Sustainsys.Saml2/Samlp/Elements/SamlStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Sustainsys.Saml2.Samlp.Elements;

/// <summary>
/// Samlp Status element
/// </summary>
public class SamlStatus
{
/// <summary>
/// Status Code
/// </summary>
public StatusCode StatusCode { get; set; } = default!;
}

/// <summary>
/// Samlp StatusCode element
/// </summary>
public class StatusCode
{
/// <summary>
/// Status code value.
/// </summary>
public string Value { get; set; } = default!;
}
2 changes: 1 addition & 1 deletion src/Sustainsys.Saml2/Samlp/RequestAbstractType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class RequestAbstractType
/// <summary>
/// Issue instant
/// </summary>
public DateTimeOffset IssueInstant { get; set; }
public DateTime IssueInstant { get; set; }

/// <summary>
/// Identifies the entity that generated the request message.
Expand Down
7 changes: 5 additions & 2 deletions src/Sustainsys.Saml2/Samlp/SamlResponse.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using Sustainsys.Saml2.Samlp.Elements;
using Sustainsys.Saml2.Xml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand All @@ -9,6 +11,7 @@ namespace Sustainsys.Saml2.Samlp;
/// <summary>
/// A Saml2p SamlResponse
/// </summary>
public class SamlResponse
public class SamlResponse : StatusResponseType
{

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Xml;
using Sustainsys.Saml2.Samlp.Attributes;
using System.Xml;

namespace Sustainsys.Saml2.Samlp;
partial class SamlpSerializer
Expand All @@ -12,9 +13,9 @@ partial class SamlpSerializer
protected virtual XmlElement Append(XmlNode parent, RequestAbstractType request, string localName)
{
var element = Append(parent, localName);
element.SetAttribute("ID", request.Id);
element.SetAttribute("IssueInstant", XmlConvert.ToString(request.IssueInstant));
element.SetAttribute("Version", request.Version);
element.SetAttribute(AttributeNames.ID, request.Id);
element.SetAttribute(AttributeNames.IssueInstant, XmlConvert.ToString(request.IssueInstant, XmlDateTimeSerializationMode.RoundtripKind));
element.SetAttribute(AttributeNames.Version, request.Version);

return element;
}
Expand Down
27 changes: 24 additions & 3 deletions src/Sustainsys.Saml2/Samlp/SamlpSerializer.SamlResponse.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Sustainsys.Saml2.Xml;
using Sustainsys.Saml2.Samlp.Elements;
using Sustainsys.Saml2.Xml;

namespace Sustainsys.Saml2.Samlp;

Expand All @@ -11,10 +12,30 @@ partial class SamlpSerializer
protected virtual SamlResponse CreateSamlResponse() => new();

/// <inheritdoc/>
public TrustedData<SamlResponse> ReadSamlResponse(XmlTraverser source)
public virtual SamlResponse ReadSamlResponse(XmlTraverser source)
{
var samlResponse = CreateSamlResponse();

return new TrustedData<SamlResponse>(TrustLevel.None, samlResponse);
if(source.EnsureName(NamespaceUri, ElementNames.Response))
{
ReadAttributes(source, samlResponse);
ReadElements(source.GetChildren(), samlResponse);
}

source.MoveNext(true);

source.ThrowOnErrors();

return samlResponse;
}

/// <summary>
/// Read elements of SamlResponse
/// </summary>
/// <param name="source">XmlTraverser</param>
/// <param name="samlResponse">SamlResponse to populate</param>
protected virtual void ReadElements(XmlTraverser source, SamlResponse samlResponse)
{
ReadElements(source, (StatusResponseType)samlResponse);
}
}
Loading

0 comments on commit 0e98e1f

Please sign in to comment.