Skip to content

Commit

Permalink
Added internal virtual on TokenHandler (#3084)
Browse files Browse the repository at this point in the history
Add AadIssuer with ValidationParameters
Added tests to AadIssuerValidator for ValidationParameters

Co-authored-by: id4s <[email protected]>
  • Loading branch information
brentschmaltz and HP712 authored Jan 21, 2025
1 parent 658604a commit 442baa3
Show file tree
Hide file tree
Showing 25 changed files with 867 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateTokenAsync(Microsoft.IdentityModel.Tokens.SecurityToken token, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.ValidatedToken>>
Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateTokenAsync(string token, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.ValidatedToken>>
Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler._telemetryClient -> Microsoft.IdentityModel.Telemetry.ITelemetryClient
override Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateTokenAsync(Microsoft.IdentityModel.Tokens.SecurityToken token, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.ValidatedToken>>
override Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateTokenAsync(string token, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.ValidatedToken>>
static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(string payload, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string
static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, string compressionAlgorithm, System.Collections.Generic.IDictionary<string, object> additionalHeaderClaims, string tokenType, bool includeKeyIdInHeader) -> string
static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public partial class JsonWebTokenHandler : TokenHandler
/// <param name="callContext">A <see cref="CallContext"/> that contains call information.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to request cancellation of the asynchronous operation.</param>
/// <returns>A <see cref="ValidationResult{TResult}"/> with either a <see cref="ValidatedToken"/> if the token was validated or an <see cref="ValidationError"/> with the failure information and exception otherwise.</returns>
internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
internal override async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
string token,
ValidationParameters validationParameters,
CallContext callContext,
Expand Down Expand Up @@ -76,7 +76,7 @@ internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
}

/// <inheritdoc/>
internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
internal override async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
SecurityToken token,
ValidationParameters validationParameters,
CallContext callContext,
Expand Down Expand Up @@ -391,7 +391,7 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext,
try
{
issuerSigningKeyValidationResult = validationParameters.IssuerSigningKeyValidator(
jsonWebToken.SigningKey, jsonWebToken, validationParameters, configuration, callContext);
jsonWebToken.SigningKey, jsonWebToken, validationParameters, callContext);

if (!issuerSigningKeyValidationResult.IsValid)
return issuerSigningKeyValidationResult.UnwrapError().AddCurrentStackFrame();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ Microsoft.IdentityModel.Tokens.Saml.SamlValidationError.SamlValidationError(Micr
Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.CreateClaimsIdentity(Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken samlToken, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, string issuer) -> System.Security.Claims.ClaimsIdentity
Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateTokenAsync(Microsoft.IdentityModel.Tokens.SecurityToken securityToken, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.ValidatedToken>>
Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateTokenAsync(string token, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.ValidatedToken>>
Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateTokenAsync(string token, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.ValidatedToken>>
Microsoft.IdentityModel.Tokens.Saml2.Saml2ValidationError
Microsoft.IdentityModel.Tokens.Saml2.Saml2ValidationError.Saml2ValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, System.Exception innerException = null) -> void
override Microsoft.IdentityModel.Tokens.Saml.SamlSecurityTokenHandler.CreateClaimsIdentityInternal(Microsoft.IdentityModel.Tokens.SecurityToken securityToken, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, string issuer) -> System.Security.Claims.ClaimsIdentity
override Microsoft.IdentityModel.Tokens.Saml.SamlValidationError.CreateException() -> System.Exception
override Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.CreateClaimsIdentityInternal(Microsoft.IdentityModel.Tokens.SecurityToken securityToken, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, string issuer) -> System.Security.Claims.ClaimsIdentity
override Microsoft.IdentityModel.Tokens.Saml.SamlValidationError.GetException() -> System.Exception
override Microsoft.IdentityModel.Tokens.Saml.SamlValidationError.GetException() -> System.Exception
override Microsoft.IdentityModel.Tokens.Saml2.Saml2ValidationError.CreateException() -> System.Exception
static Microsoft.IdentityModel.Tokens.Saml.SamlSecurityTokenHandler.StackFrames.SignatureValidationFailed -> System.Diagnostics.StackFrame
static Microsoft.IdentityModel.Tokens.Saml.SamlSecurityTokenHandler.ValidateSignature(Microsoft.IdentityModel.Tokens.Saml.SamlSecurityToken samlToken, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext) -> Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.SecurityKey>
static Microsoft.IdentityModel.Tokens.Saml.SamlTokenUtilities.PopulateValidationParametersWithCurrentConfigurationAsync(Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.IdentityModel.Tokens.ValidationParameters>
static Microsoft.IdentityModel.Tokens.Saml.SamlTokenUtilities.ResolveTokenSigningKey(Microsoft.IdentityModel.Xml.KeyInfo tokenKeyInfo, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters) -> Microsoft.IdentityModel.Tokens.SecurityKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public partial class SamlSecurityTokenHandler : SecurityTokenHandler
/// <param name="callContext">A <see cref="CallContext"/> that contains call information.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to request cancellation of the asynchronous operation.</param>
/// <returns>A <see cref="ValidationResult{TResult}"/> with either a <see cref="ValidatedToken"/> if the token was validated or an <see cref="ValidationError"/> with the failure information and exception otherwise.</returns>
internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
internal async override Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
string token,
ValidationParameters validationParameters,
CallContext callContext,
Expand All @@ -43,7 +43,7 @@ internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
return await ValidateTokenAsync(tokenReadingResult.UnwrapResult(), validationParameters, callContext, cancellationToken).ConfigureAwait(false);
}

internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
internal override async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
SecurityToken securityToken,
ValidationParameters validationParameters,
CallContext callContext,
Expand Down Expand Up @@ -150,7 +150,6 @@ internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
samlToken.SigningKey,
samlToken,
validationParameters,
null,
callContext);

if (!issuerSigningKeyValidationResult.IsValid)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public partial class Saml2SecurityTokenHandler : SecurityTokenHandler
/// <param name="callContext">A <see cref="CallContext"/> that contains call information.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to request cancellation of the asynchronous operation.</param>
/// <returns>A <see cref="ValidationResult{TResult}"/> with either a <see cref="ValidatedToken"/> if the token was validated or an <see cref="ValidationError"/> with the failure information and exception otherwise.</returns>
internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
internal override async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
string token,
ValidationParameters validationParameters,
CallContext callContext,
Expand All @@ -44,7 +44,7 @@ internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
return await ValidateTokenAsync(tokenReadingResult.UnwrapResult(), validationParameters, callContext, cancellationToken).ConfigureAwait(false);
}

internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
internal override async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
SecurityToken securityToken,
ValidationParameters validationParameters,
CallContext callContext,
Expand Down Expand Up @@ -155,7 +155,6 @@ internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
samlToken.SigningKey,
samlToken,
validationParameters,
null,
callContext);

if (!issuerSigningKeyValidationResult.IsValid)
Expand Down
2 changes: 2 additions & 0 deletions src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,5 @@ static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.TokenIsNotS
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.TokenReplayValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.TokenTypeValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.XmlValidationFailed -> Microsoft.IdentityModel.Tokens.ValidationFailureType
virtual Microsoft.IdentityModel.Tokens.TokenHandler.ValidateTokenAsync(Microsoft.IdentityModel.Tokens.SecurityToken token, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.ValidatedToken>>
virtual Microsoft.IdentityModel.Tokens.TokenHandler.ValidateTokenAsync(string token, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.ValidatedToken>>
46 changes: 46 additions & 0 deletions src/Microsoft.IdentityModel.Tokens/TokenHandler.Internal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Threading;
using System.Threading.Tasks;
using static Microsoft.IdentityModel.Logging.LogHelper;

namespace Microsoft.IdentityModel.Tokens
{
/// <summary>
/// Defines properties shared across all security token handlers.
/// </summary>
public abstract partial class TokenHandler
{
internal virtual Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
string token,
ValidationParameters validationParameters,
CallContext callContext,
CancellationToken cancellationToken)
{
throw LogExceptionMessage(
new NotImplementedException(
FormatInvariant(
LogMessages.IDX10267,
MarkAsNonPII("internal virtual Task<ValidationResult<ValidatedToken>> " +
"ValidateTokenAsync(string token, ValidationParameters validationParameters, CallContext callContext, CancellationToken cancellationToken)"),
MarkAsNonPII(GetType().FullName))));
}

internal virtual Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
SecurityToken token,
ValidationParameters validationParameters,
CallContext callContext,
CancellationToken cancellationToken)
{
throw LogExceptionMessage(
new NotImplementedException(
FormatInvariant(
LogMessages.IDX10267,
MarkAsNonPII("internal virtual Task<ValidationResult<ValidatedToken>> " +
"ValidateTokenAsync(SecurityToken token, ValidationParameters validationParameters, CallContext callContext, CancellationToken cancellationToken)"),
MarkAsNonPII(GetType().FullName))));
}
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.IdentityModel.Tokens/TokenHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Microsoft.IdentityModel.Tokens
/// <summary>
/// Defines properties shared across all security token handlers.
/// </summary>
public abstract class TokenHandler
public abstract partial class TokenHandler
{
private int _defaultTokenLifetimeInMinutes = DefaultTokenLifetimeInMinutes;
private int _maximumTokenSizeInBytes = TokenValidationParameters.DefaultMaximumTokenSizeInBytes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal class ValidationParameters
private string _roleClaimType = ClaimsIdentity.DefaultRoleClaimType;
private Dictionary<string, object>? _instancePropertyBag;
private IList<SecurityKey>? _issuerSigningKeys;
private IDictionary<string, object>? _propertyBag;
private Dictionary<string, object>? _propertyBag;
private IList<SecurityKey>? _tokenDecryptionKeys;
private IList<string>? _validIssuers;
private IList<string>? _validTokenTypes;
Expand Down Expand Up @@ -83,7 +83,9 @@ protected ValidationParameters(ValidationParameters other)
LogTokenId = other.LogTokenId;
NameClaimType = other.NameClaimType;
NameClaimTypeRetriever = other.NameClaimTypeRetriever;
_propertyBag = other.PropertyBag;
foreach (var keyValue in other.PropertyBag)
PropertyBag[keyValue.Key] = keyValue.Value;

RefreshBeforeValidation = other.RefreshBeforeValidation;
RoleClaimType = other.RoleClaimType;
RoleClaimTypeRetriever = other.RoleClaimTypeRetriever;
Expand Down Expand Up @@ -290,7 +292,9 @@ public IssuerSigningKeyValidationDelegate IssuerSigningKeyValidator
/// Calling <see cref="Clone"/> will result in a new instance of this IDictionary.
/// </summary>
public IDictionary<string, object> InstancePropertyBag =>
_instancePropertyBag ??= new Dictionary<string, object>();
_instancePropertyBag ??
Interlocked.CompareExchange(ref _instancePropertyBag, [], null) ??
_instancePropertyBag;

/// <summary>
/// Gets a value indicating if <see cref="Clone"/> was called to obtain this instance.
Expand Down Expand Up @@ -389,7 +393,9 @@ public string NameClaimType
/// Gets or sets the <see cref="IDictionary{TKey, TValue}"/> that contains a collection of custom key/value pairs.
/// This allows addition of parameters that could be used in custom token validation scenarios.
/// </summary>
public IDictionary<string, object> PropertyBag => _propertyBag ??= new Dictionary<string, object>();
public IDictionary<string, object> PropertyBag => _propertyBag ??
Interlocked.CompareExchange(ref _propertyBag, [], null) ??
_propertyBag;

/// <summary>
/// A boolean to control whether configuration should be refreshed before validating a token.
Expand Down
Loading

0 comments on commit 442baa3

Please sign in to comment.