Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 29, 2026

SAMLRequest Signature Validation Implementation - COMPLETE ✅

  • Add method to validate incoming SAMLRequest signatures from Federator
    • Create ValidateFederatorRequestSignature method in ISAMLService interface
    • Implement ValidateFederatorRequestSignature in SAMLService
    • Method fetches Federator metadata and extracts certificates
    • Verifies signature using RSA public key from Federator certificate
    • Uses same pattern as IdP metadata fetching
    • Add metadata caching to improve performance (configurable, default 240 min)
    • Support multiple signature algorithms (RSA-SHA256, RSA-SHA1, RSA-SHA512)
    • Add XML documentation to the method
    • Distinguish between validation failures and infrastructure errors
    • Set PreserveWhitespace=true for XML parsing
  • Integrate signature validation in ProxyController
    • Call validation after SAMLRequest decode and before processing
    • Handle validation failures with proper error logging
    • Use dedicated FederatorRequestValidation configuration (not TechnicalChecks)
    • Handle InvalidOperationException for configuration errors
  • Add logging events for signature validation
    • SAML_REQUEST_SIGNATURE_VALIDATED (5009)
    • ERROR_INVALID_SAML_REQUEST_SIGNATURE (9008)
  • Build the project successfully
  • Run security check with CodeQL (0 vulnerabilities found)
  • Address all PR feedback
    • Created dedicated FederatorRequestValidationOptions
    • Support RSA-SHA1, RSA-SHA256, RSA-SHA512 algorithms
    • Made cache key a constant
    • Made cache expiration configurable (default 240 min)
    • Refactored SigAlg validation using switch expression for better readability
    • Added cross-platform compatibility comment for RSA verification

Summary

All feedback addressed. The implementation now:

  • Uses dedicated FederatorRequestValidation config section
  • Supports multiple SAML signature algorithms with readable switch expression
  • Has constant for cache key
  • Has configurable cache expiration with 240 min default
  • Confirmed cross-platform compatible (Windows/Linux)
Original prompt

This section details on the original issue you should resolve

<issue_title>Validate SAMLRequest Signature</issue_title>
<issue_description>We should validate the SAMLRequest signature incoming from the Federator to have an additional layer of security</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits January 29, 2026 17:50
Co-authored-by: fume <2969850+fume@users.noreply.github.com>
…umentation, better error handling

Co-authored-by: fume <2969850+fume@users.noreply.github.com>
Copilot AI changed the title [WIP] Add validation for SAMLRequest signature Validate SAMLRequest signatures from Federator Jan 29, 2026
Copilot AI requested a review from fume January 29, 2026 17:58
}

// Validate SAMLRequest signature from Federator
if (!_technicalChecksOptions.SkipSignaturesValidation)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need a dedicated option to skip the SAMLRequest signature validation. Definetely not on the technical checks options which are dedicated to samlresponse validation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created dedicated FederatorRequestValidationOptions with SkipSAMLRequestSignatureValidation setting. The ProxyController now uses this instead of TechnicalChecks options. Configuration is in the new FederatorRequestValidation section in appsettings.json. (commit 0a13bec)

Comment on lines 137 to 143
// Decode and validate that SigAlg matches expected algorithm
string decodedSigAlg = HttpUtility.UrlDecode(federatorRequest.SigAlg);
if (!decodedSigAlg.Equals("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", StringComparison.OrdinalIgnoreCase))
{
_logger.LogWarning("SAMLRequest SigAlg '{sigAlg}' is not supported. Expected rsa-sha256", decodedSigAlg);
return false;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we support even other signature algorithms? IF not, explain why

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now supports RSA-SHA256, RSA-SHA1, and RSA-SHA512 per SAML specifications. The algorithm is detected from the SigAlg parameter and the corresponding HashAlgorithmName is used for signature verification. These are the standard algorithms supported by SAML HTTP-Redirect binding. (commit 0a13bec)


// Try to get metadata from cache first
string metadataXml = null;
string cacheKey = "FederatorMetadata";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this a constant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the cache key a constant FEDERATOR_METADATA_CACHE_KEY at the class level. (commit 0a13bec)

{
var options = new DistributedCacheEntryOptions()
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(120),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this configurable, with a default of 240 minutes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made cache expiration configurable via FederatorRequestValidationOptions.MetadataCacheAbsoluteExpirationInMins with a default of 240 minutes. Can be configured in appsettings.json under FederatorRequestValidation section. (commit 0a13bec)

Copy link
Collaborator

@fume fume left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…, support multiple signature algorithms, use constant for cache key

Co-authored-by: fume <2969850+fume@users.noreply.github.com>
Copilot AI requested a review from fume January 29, 2026 21:51
Comment on lines 147 to 159
if (decodedSigAlg.Equals("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", StringComparison.OrdinalIgnoreCase))
{
hashAlgorithm = HashAlgorithmName.SHA256;
}
else if (decodedSigAlg.Equals("http://www.w3.org/2000/09/xmldsig#rsa-sha1", StringComparison.OrdinalIgnoreCase))
{
hashAlgorithm = HashAlgorithmName.SHA1;
}
else if (decodedSigAlg.Equals("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", StringComparison.OrdinalIgnoreCase))
{
hashAlgorithm = HashAlgorithmName.SHA512;
}
else
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rewrite this block using a more readable switch case. Keep the logging for the unsupported SigAlg.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored to use a switch expression for better readability. The logging for unsupported SigAlg is preserved. (commit c0fe19c)

Comment on lines 247 to 257
foreach (var cert in certificates)
{
using (RSA rsa = cert.GetRSAPublicKey())
{
if (rsa != null && rsa.VerifyData(bytesToVerify, signatureBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1))
if (rsa != null && rsa.VerifyData(bytesToVerify, signatureBytes, hashAlgorithm, RSASignaturePadding.Pkcs1))
{
_logger.LogDebug("SAMLRequest signature validated successfully with certificate: {subject}", cert.Subject);
return true;
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double check if this code is cross-platform. This solution could run both on windows and linux

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed cross-platform compatible. The GetRSAPublicKey() and VerifyData() methods are part of the standard .NET cryptography library that works on both Windows and Linux. This pattern is already used elsewhere in the codebase (FederatorResponseService, XMLSignatureExtensions). Added a comment to explicitly document cross-platform compatibility. (commit c0fe19c)

Copy link
Collaborator

@fume fume left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…tform compatibility comment

Co-authored-by: fume <2969850+fume@users.noreply.github.com>
Copilot AI requested a review from fume January 29, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validate SAMLRequest Signature

2 participants