ITfoxtec SAML 2.0: InvalidSignatureException When Configuring AWS SSO

Viewed 397

I have a small test app that I have successfully integrated with Okta as the IdP. I have also set up AWS SSO to serve as an IdP. When I switch my app over to use AWS SSO, I get the following error:

ITfoxtec.Identity.Saml2.Cryptography.InvalidSignatureException: Signature is invalid.
   at ITfoxtec.Identity.Saml2.Saml2Request.ValidateXmlSignature(SignatureValidation documentValidationResult)
   at ITfoxtec.Identity.Saml2.Saml2Request.Read(String xml, Boolean validateXmlSignature)
   at ITfoxtec.Identity.Saml2.Saml2Response.Read(String xml, Boolean validateXmlSignature)
   at ITfoxtec.Identity.Saml2.Saml2AuthnResponse.Read(String xml, Boolean validateXmlSignature)
   at ITfoxtec.Identity.Saml2.Saml2PostBinding.Read(HttpRequest request, Saml2Request saml2RequestResponse, String messageName, Boolean validateXmlSignature)
   at ITfoxtec.Identity.Saml2.Saml2PostBinding.UnbindInternal(HttpRequest request, Saml2Request saml2RequestResponse, String messageName)
   at ITfoxtec.Identity.Saml2.Saml2Binding`1.Unbind(HttpRequest request, Saml2Response saml2Response)
   at SAML_Example.Controllers.AuthController.AssertionConsumerService() in C:\Workspace\saml\SAML_Example\AuthController.cs:line 46
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

I have verified that the Signature Algorithm being returned from AWS SSO matches what Okta returned, http://www.w3.org/2001/04/xmldsig-more#rsa-sha256. Has anyone successfully configured ITfoxtec with AWS SSO?

2 Answers

Are the integration to Okta and AWS based on there metadata or do you configure the trust to the external IdP by configuring the IdP certificate?

It sounds like you are validating the AWS IdP against an incorrect certificate.

It is my understanding that usually the assertion tag is what is signed. In AWS's case, they sign the assertion tag as well as the entire response. The assertion tag's signature does not validate for me the but the signature for the entire response does. I figure since the assertion is in the response, it can be considered valid as well.

I removed the call to unbind and replaced it with the following:

var certValidation = true;
var cert = _samlConfig.SignatureValidationCertificates.FirstOrDefault();
var nodes = saml2AuthnResponse.XmlDocument.SelectNodes("//*[local-name()='Signature']").ToEnumerable().ToList();
var responseSignature = nodes.FirstOrDefault(n => n?.ParentNode?.LocalName == "Response");
if (responseSignature != null)
{
    var signedXml = new SignedXml(responseSignature.ParentNode as XmlElement);
    signedXml.LoadXml(responseSignature as XmlElement);
    certValidation = signedXml.CheckSignature(cert, true);
}
else
{
    foreach (var node in nodes)
    {
        var signedXml = new SignedXml(node.ParentNode as XmlElement);
        signedXml.LoadXml(node as XmlElement);
        certValidation = certValidation && signedXml.CheckSignature(cert, true);
    }
}

If there is no signature on the overall response, it reverts back to the original behavior and checks every signature present.

Related