Skip to content

Conversation

brentschmaltz
Copy link
Contributor

Validation steps for all but Signature have been redesigned so that each token handler will call the same validation method.
Each validation step will return a ValidationError that is associated with that step.
For example, AudienceValidation will return a result (string) OR an AudienceValidationError.

An internal ValidationStep, such as ValidateAudienceInternal was created so the users can hook a custom validation step, then call into the default, ValidateAudience, if desired.

Each ValidationError derived type will return an Exception associated with the error.
For example, AudienceValiationError will return SecurityTokenInvalidAudienceException.

ValidationFailureTypes are now hierarchial.

Tests for Extensibility, TokenValidation were rewritten in a token agnostic manner so that a validation step returned the same results regardless of JWT, Saml or Saml2.
Test results were compared to the previous validation logic using TokenValidationParameters to ensure correctness.

Saml and Saml2 tokens now share the same signature validation logic.
Saml and Saml2 validation step called ValidateConditions was replaced with ValidateAudience, ValidateLifetime to be consistent with JWT.

Code that was not used or not needed was removed.
Names of some properties were renamed, such as ValidationParameters.IssuerSigningKeys -> ValidationParameters.SignatureKeys.
Some names were shortened, ValidationParameters.TokenDecryptionKeys -> ValidationParameters.DecryptionKeys.

Redundant tests were removed.

This is still experimental code and there needs to be additional work before shipping such as:

  1. Additional tests
  2. Consolidation of tests
  3. Review naming
  4. Review error messages.
  5. Removing the 'Experimental' namespace.

@brentschmaltz brentschmaltz requested a review from a team as a code owner July 23, 2025 18:07
@brentschmaltz brentschmaltz changed the title Update return from validation steps to use M.Abstractions.OperationResult Update return from validation steps to use M.I.Abstractions.OperationResult Jul 23, 2025
@pmaytak pmaytak requested a review from Copilot July 25, 2025 15:54
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR updates validation step return types from ValidationResult to use OperationResult from M.I.Abstractions, as part of redesigning the validation architecture. The validation steps now return ValidationError objects that are hierarchical, and validation logic has been consolidated across JWT, SAML, and SAML2 tokens to be token-agnostic.

Key Changes:

  • Modified validation delegates to return OperationResult<T, ValidationError> instead of custom ValidationResult types
  • Updated ValidationError classes to use new exception patterns and remove ExceptionType dependencies
  • Consolidated validation logic across token types to be token-agnostic
  • Renamed properties (IssuerSigningKeys → SignatureKeys, TokenDecryptionKeys → DecryptionKeys)

Reviewed Changes

Copilot reviewed 137 out of 200 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
ExtensibilityTheoryData.cs Updated base test class to use TokenHandler and SecurityToken directly instead of string types
CustomValidationErrors.cs Refactored validation error classes to use new exception patterns and remove ExceptionType references
CustomTokenTypeValidationDelegates.cs Updated delegates to return OperationResult and use new validation failure types
CustomTokenReplayValidationDelegates.cs Updated delegates to return OperationResult and use new validation failure types
CustomSignatureValidationDelegates.cs Updated delegates to return OperationResult and use new validation failure types
CustomLifetimeValidationDelegates.cs Updated delegates to return OperationResult and use new validation failure types
CustomIssuerValidationDelegates.cs Updated delegates to return OperationResult and use new validation failure types
CustomIssuerSigningKeyValidationDelegates.cs Updated delegates to return OperationResult and use new validation failure types
CustomExceptions.cs Updated custom exception constructors to accept ValidationError parameters
CustomAudienceValidationDelegates.cs Updated delegates to return OperationResult and use new validation failure types
CustomAlgorithmValidationDelegates.cs Updated delegates to return OperationResult and use new validation failure types
TestUtilities.cs Updated property names from IssuerSigningKeys to SignatureKeys
TestCaseProvider.cs Added comprehensive test case provider for various validation scenarios
SkipValidationDelegates.cs Updated delegate signatures and return types
SamlClaimsIdentityComparisonTestBase.cs Updated to use OperationResult and new property names
IdentityComparer.cs Updated validation error comparison logic
ITestingTokenHandler.cs Complete rewrite of testing token handler interface and implementations
Comments suppressed due to low confidence (4)

test/Microsoft.IdentityModel.TestUtils/TokenValidationExtensibility/CustomValidationErrors.cs:4

  • Remove commented-out using statements. These should be deleted rather than commented out to maintain code cleanliness.
using System;

test/Microsoft.IdentityModel.TestUtils/TokenValidationExtensibility/CustomValidationErrors.cs:4

  • Remove commented-out using statements. These should be deleted rather than commented out to maintain code cleanliness.
using System;

test/Microsoft.IdentityModel.TestUtils/TokenValidationExtensibility/CustomAudienceValidationDelegates.cs:66

  • Misplaced semicolon after the constructor call. The semicolon should be on the same line as the closing parenthesis rather than on a separate line.
                null)

test/Microsoft.IdentityModel.TestUtils/TokenValidationExtensibility/CustomAudienceValidationDelegates.cs:67

  • Unnecessary semicolon on separate line. This should be removed or moved to the previous line.
                ;

Copy link

Summary

Summary
Generated on: 7/28/2025 - 5:04:06 PM
Coverage date: 7/28/2025 - 4:53:40 PM - 7/28/2025 - 5:03:36 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@brentschmaltz brentschmaltz force-pushed the brentsch/ValidationError branch 2 times, most recently from 81e78cf to d53180e Compare July 28, 2025 18:13
Copy link

Summary

Summary
Generated on: 7/28/2025 - 6:21:21 PM
Coverage date: 7/28/2025 - 6:11:01 PM - 7/28/2025 - 6:20:53 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

Copy link

Summary

Summary
Generated on: 7/28/2025 - 6:25:51 PM
Coverage date: 7/28/2025 - 6:15:26 PM - 7/28/2025 - 6:25:21 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

Copy link

Summary

Summary
Generated on: 7/28/2025 - 6:27:21 PM
Coverage date: 7/28/2025 - 6:16:11 PM - 7/28/2025 - 6:26:54 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@brentschmaltz brentschmaltz force-pushed the brentsch/ValidationError branch from d53180e to a8712df Compare July 28, 2025 18:35
Copy link

Summary

Summary
Generated on: 7/28/2025 - 6:49:20 PM
Coverage date: 7/28/2025 - 6:38:17 PM - 7/28/2025 - 6:48:52 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@brentschmaltz brentschmaltz force-pushed the brentsch/ValidationError branch from a8712df to 5c5e9aa Compare July 28, 2025 21:00
Copy link

Summary

Summary
Generated on: 7/28/2025 - 9:13:25 PM
Coverage date: 7/28/2025 - 9:02:58 PM - 7/28/2025 - 9:13:00 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

Standardize validation across token types.
@brentschmaltz brentschmaltz force-pushed the brentsch/ValidationError branch from 5c5e9aa to 4d49ed4 Compare August 1, 2025 16:02
Copy link

github-actions bot commented Aug 1, 2025

Summary

Summary
Generated on: 8/1/2025 - 4:16:17 PM
Coverage date: 8/1/2025 - 4:05:32 PM - 8/1/2025 - 4:15:34 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

Copy link

github-actions bot commented Aug 1, 2025

Summary

Summary
Generated on: 8/1/2025 - 6:30:48 PM
Coverage date: 8/1/2025 - 6:20:14 PM - 8/1/2025 - 6:30:09 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@brentschmaltz brentschmaltz merged commit 35cc68b into dev Aug 1, 2025
6 checks passed
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.

4 participants