diff --git a/build/dependencies.props b/build/dependencies.props
index 3acadea8e2..e7f8afdb8c 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -5,6 +5,7 @@
3.3.4
8.0.1
4.5.0
+ 8.0.2
1.0.0
2.0.3
13.0.3
diff --git a/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt
index 5a8febaf08..c05846e38a 100644
--- a/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt
+++ b/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt
@@ -27,6 +27,7 @@ Microsoft.IdentityModel.Tokens.IssuerValidationSource.IssuerMatchedValidationPar
Microsoft.IdentityModel.Tokens.LifetimeValidationError.Expires.get -> System.DateTime?
Microsoft.IdentityModel.Tokens.LifetimeValidationError.LifetimeValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, System.DateTime? notBefore, System.DateTime? expires, System.Exception innerException = null) -> void
Microsoft.IdentityModel.Tokens.LifetimeValidationError.NotBefore.get -> System.DateTime?
+Microsoft.IdentityModel.Tokens.LoggingEventId
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidOperationException
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidOperationException.SecurityTokenInvalidOperationException() -> void
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidOperationException.SecurityTokenInvalidOperationException(string message) -> void
@@ -43,13 +44,16 @@ Microsoft.IdentityModel.Tokens.TokenTypeValidationError.InvalidTokenType.get ->
Microsoft.IdentityModel.Tokens.TokenTypeValidationError.TokenTypeValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, string invalidTokenType, System.Exception innerException = null) -> void
Microsoft.IdentityModel.Tokens.TokenValidationParameters.TimeProvider.get -> System.TimeProvider
Microsoft.IdentityModel.Tokens.TokenValidationParameters.TimeProvider.set -> void
+Microsoft.IdentityModel.Tokens.ValidatedToken.Log(Microsoft.Extensions.Logging.ILogger logger) -> void
Microsoft.IdentityModel.Tokens.ValidationError.AddCurrentStackFrame(string filePath = "", int lineNumber = 0, int skipFrames = 1) -> Microsoft.IdentityModel.Tokens.ValidationError
Microsoft.IdentityModel.Tokens.ValidationError.GetException(System.Type exceptionType, System.Exception innerException) -> System.Exception
+Microsoft.IdentityModel.Tokens.ValidationError.Log(Microsoft.Extensions.Logging.ILogger logger) -> void
Microsoft.IdentityModel.Tokens.ValidationError.ValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, System.Exception innerException = null) -> void
Microsoft.IdentityModel.Tokens.ValidationParameters.TokenTypeValidator.get -> Microsoft.IdentityModel.Tokens.TokenTypeValidationDelegate
Microsoft.IdentityModel.Tokens.ValidationParameters.TokenTypeValidator.set -> void
Microsoft.IdentityModel.Tokens.ValidationResult.Error.get -> Microsoft.IdentityModel.Tokens.ValidationError
Microsoft.IdentityModel.Tokens.ValidationResult.IsValid.get -> bool
+Microsoft.IdentityModel.Tokens.ValidationResult.Log(Microsoft.Extensions.Logging.ILogger logger) -> void
Microsoft.IdentityModel.Tokens.ValidationResult.Result.get -> TResult
override Microsoft.IdentityModel.Tokens.AlgorithmValidationError.GetException() -> System.Exception
override Microsoft.IdentityModel.Tokens.IssuerSigningKeyValidationError.GetException() -> System.Exception
@@ -62,6 +66,8 @@ static Microsoft.IdentityModel.Tokens.TokenReplayValidationError.NullParameter(s
static Microsoft.IdentityModel.Tokens.TokenTypeValidationError.NullParameter(string parameterName, System.Diagnostics.StackFrame stackFrame) -> Microsoft.IdentityModel.Tokens.TokenTypeValidationError
static Microsoft.IdentityModel.Tokens.Utility.SerializeAsSingleCommaDelimitedString(System.Collections.Generic.IList strings) -> string
static Microsoft.IdentityModel.Tokens.ValidationError.GetCurrentStackFrame(string filePath = "", int lineNumber = 0, int skipFrames = 1) -> System.Diagnostics.StackFrame
+static readonly Microsoft.IdentityModel.Tokens.LoggingEventId.TokenValidationFailed -> Microsoft.Extensions.Logging.EventId
+static readonly Microsoft.IdentityModel.Tokens.LoggingEventId.TokenValidationSucceeded -> Microsoft.Extensions.Logging.EventId
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.AlgorithmValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.AudienceValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.IssuerSigningKeyValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType
diff --git a/src/Microsoft.IdentityModel.Tokens/LoggingEventId.cs b/src/Microsoft.IdentityModel.Tokens/LoggingEventId.cs
new file mode 100644
index 0000000000..aa682a3dd5
--- /dev/null
+++ b/src/Microsoft.IdentityModel.Tokens/LoggingEventId.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.Extensions.Logging;
+
+namespace Microsoft.IdentityModel.Tokens
+{
+ internal static class LoggingEventId
+ {
+ // TokenValidation EventIds 100+
+ internal static readonly EventId TokenValidationFailed = new(100, "TokenValidationFailed");
+ internal static readonly EventId TokenValidationSucceeded = new(101, "TokenValidationSucceeded");
+ }
+}
diff --git a/src/Microsoft.IdentityModel.Tokens/Microsoft.IdentityModel.Tokens.csproj b/src/Microsoft.IdentityModel.Tokens/Microsoft.IdentityModel.Tokens.csproj
index 459a772334..2e3b454bbf 100644
--- a/src/Microsoft.IdentityModel.Tokens/Microsoft.IdentityModel.Tokens.csproj
+++ b/src/Microsoft.IdentityModel.Tokens/Microsoft.IdentityModel.Tokens.csproj
@@ -72,5 +72,9 @@
+
+
+
+
diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ValidationError.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ValidationError.cs
index fb8481d1ac..b4e0a6714f 100644
--- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ValidationError.cs
+++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ValidationError.cs
@@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
+using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Logging;
#nullable enable
@@ -183,6 +184,11 @@ internal Exception GetException(Type exceptionType, Exception? innerException)
return exception;
}
+ internal void Log(ILogger logger)
+ {
+ Logger.TokenValidationFailed(logger, FailureType.Name, MessageDetail.Message);
+ }
+
internal static ValidationError NullParameter(string parameterName, StackFrame stackFrame) => new(
MessageDetail.NullParameter(parameterName),
ValidationFailureType.NullArgument,
@@ -261,6 +267,27 @@ internal static StackFrame GetCurrentStackFrame(
// ConcurrentDictionary is thread-safe and only locks when adding a new item.
private static ConcurrentDictionary CachedStackFrames { get; } = new();
+
+ private static class Logger
+ {
+ private static readonly Action s_tokenValidationFailed =
+ LoggerMessage.Define(
+ LogLevel.Information,
+ LoggingEventId.TokenValidationFailed,
+ "[MsIdentityModel] The token validation was unsuccessful due to: {ValidationFailureType} " +
+ "Error message provided: {ValidationErrorMessage}");
+
+ ///
+ /// Logger for handling failures in token validation.
+ ///
+ /// ILogger.
+ /// The cause of the failure.
+ /// The message provided as part of the failure.
+ public static void TokenValidationFailed(
+ ILogger logger,
+ string validationFailureType,
+ string messageDetail) => s_tokenValidationFailed(logger, validationFailureType, messageDetail, null);
+ }
}
}
#nullable restore
diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidatedToken.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidatedToken.cs
index 3722fc4e8e..7eccd96c75 100644
--- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidatedToken.cs
+++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidatedToken.cs
@@ -6,6 +6,7 @@
using System.Diagnostics;
using System.Security.Claims;
using System.Threading;
+using Microsoft.Extensions.Logging;
#nullable enable
namespace Microsoft.IdentityModel.Tokens
@@ -34,11 +35,17 @@ internal ValidatedToken(
///
/// Logs the validation result.
///
-#pragma warning disable CA1822 // Mark members as static
- public void Log()
-#pragma warning restore CA1822 // Mark members as static
+ public void Log(ILogger logger)
{
- // TODO - Do we need this, how will it work?
+ Logger.TokenValidationSucceeded(
+ logger,
+ ValidatedAudience ?? "none",
+ ValidatedLifetime,
+ ValidatedIssuer,
+ ValidatedTokenType,
+ ValidatedSigningKey?.KeyId ?? "none",
+ ActorValidationResult is not null
+ );
}
public SecurityToken SecurityToken { get; private set; }
@@ -168,6 +175,68 @@ private object ClaimsIdentitySyncObj
}
}
#endregion
+
+ #region Logging
+ private static class Logger
+ {
+ private static readonly Action s_tokenValidationFailed =
+ LoggerMessage.Define(
+ LogLevel.Information,
+ LoggingEventId.TokenValidationFailed,
+ "[MsIdentityModel] The token validation was unsuccessful due to: {ValidationFailureType} " +
+ "Error message provided: {ValidationErrorMessage}");
+
+ ///
+ /// Logger for handling failures in token validation.
+ ///
+ /// ILogger.
+ /// The cause of the failure.
+ /// The message provided as part of the failure.
+ public static void TokenValidationFailed(
+ ILogger logger,
+ ValidationFailureType validationFailureType,
+ MessageDetail messageDetail) => s_tokenValidationFailed(logger, validationFailureType.Name, messageDetail.Message, null);
+
+ private static readonly Action s_tokenValidationSucceeded =
+ LoggerMessage.Define(
+ LogLevel.Debug,
+ LoggingEventId.TokenValidationSucceeded,
+ "[MsIdentityModel] The token validation was successful. " +
+ "Validated audience: {ValidatedAudience} " +
+ "Validated lifetime: {ValidatedLifetime} " +
+ "Validated issuer: {ValidatedIssuer} " +
+ "Validated token type: {ValidatedTokenType} " +
+ "Validated signing key id: {ValidatedSigningKeyId} " +
+ "Actor was validated: {ActorWasValidated}");
+
+ ///
+ /// Logger for handling successful token validation.
+ ///
+ /// The instance to be used to log.
+ /// The audience that was validated.
+ /// The lifetime that was validated.
+ /// The issuer that was validated.
+ /// The token type that was validated.
+ /// The signing key id that was validated.
+ /// Whether the actor was validated.
+ public static void TokenValidationSucceeded(
+ ILogger logger,
+ string validatedAudience,
+ ValidatedLifetime? validatedLifetime,
+ ValidatedIssuer? validatedIssuer,
+ ValidatedTokenType? validatedTokenType,
+ string validatedSigningKeyId,
+ bool actorWasValidated) => s_tokenValidationSucceeded(
+ logger,
+ validatedAudience,
+ validatedLifetime,
+ validatedIssuer,
+ validatedTokenType,
+ validatedSigningKeyId,
+ actorWasValidated,
+ null);
+ }
+ #endregion
}
}
#nullable disable