Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add framework for reducing exceptions and logging. #2628

Merged
merged 2 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Wilson.sln
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4655DBB4-70C6-475D-8971-FE6619B85F70}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
buildPack.bat = buildPack.bat
buildTestPack.bat = buildTestPack.bat
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.IdentityModel.Validators", "src\Microsoft.IdentityModel.Validators\Microsoft.IdentityModel.Validators.csproj", "{DA585910-0E6C-45A5-AABD-30917130FD63}"
Expand Down
1 change: 1 addition & 0 deletions buildPack.bat
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
dotnet clean Product.proj > clean.log
dotnet build /r Product.proj
dotnet pack --no-restore -o artifacts --no-build Product.proj
1 change: 1 addition & 0 deletions buildTestPack.bat
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dotnet clean Product.proj > clean.log
dotnet build /r Product.proj
dotnet test --no-restore --no-build Product.proj
dotnet pack --no-restore -o artifacts --no-build Product.proj

Large diffs are not rendered by default.

545 changes: 0 additions & 545 deletions src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@
// Licensed under the MIT License.

using System;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Text;
using Microsoft.IdentityModel.Logging;

namespace Microsoft.IdentityModel.Tokens
{

/// <summary>
/// Represents a security token exception.
/// </summary>
[Serializable]
public class SecurityTokenException : Exception
{
[NonSerialized]
private string _stackTrace;

/// <summary>
/// Initializes a new instance of the <see cref="SecurityTokenException"/> class.
/// </summary>
Expand Down Expand Up @@ -55,6 +59,49 @@ protected SecurityTokenException(SerializationInfo info, StreamingContext contex
{
}

/// <summary>
/// Gets the stack trace that is captured when the exception is created.
/// </summary>
public override string StackTrace
{
get
{
if (_stackTrace == null)
{
if (ExceptionDetail == null)
return base.StackTrace;
#if NET8_0_OR_GREATER
_stackTrace = new StackTrace(ExceptionDetail.StackFrames).ToString();
#else
StringBuilder sb = new();
foreach (StackFrame frame in ExceptionDetail.StackFrames)
{
sb.Append(frame.ToString());
sb.Append(Environment.NewLine);
}

_stackTrace = sb.ToString();
#endif
}

return _stackTrace;
}
}

/// <summary>
/// Gets or sets the source of the exception.
/// </summary>
public override string Source
{
get => base.Source;
set => base.Source = value;
}

internal ExceptionDetail ExceptionDetail
{
get; set;
}

#if NET472 || NETSTANDARD2_0 || NET6_0_OR_GREATER
/// <summary>
/// When overridden in a derived class, sets the System.Runtime.Serialization.SerializationInfo
Expand Down
4 changes: 3 additions & 1 deletion src/Microsoft.IdentityModel.Tokens/LogMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal static class LogMessages
public const string IDX10207 = "IDX10207: Unable to validate audience. The 'audiences' parameter is null.";
public const string IDX10208 = "IDX10208: Unable to validate audience. validationParameters.ValidAudience is null or whitespace and validationParameters.ValidAudiences is null.";
public const string IDX10209 = "IDX10209: Token has length: '{0}' which is larger than the MaximumTokenSizeInBytes: '{1}'.";
public const string IDX10211 = "IDX10211: Unable to validate issuer. The 'issuer' parameter is null or whitespace";
public const string IDX10211 = "IDX10211: Unable to validate issuer. The 'issuer' parameter is null or whitespace.";
public const string IDX10214 = "IDX10214: Audience validation failed. Audiences: '{0}'. Did not match: validationParameters.ValidAudience: '{1}' or validationParameters.ValidAudiences: '{2}'.";
public const string IDX10222 = "IDX10222: Lifetime validation failed. The token is not yet valid. ValidFrom (UTC): '{0}', Current time (UTC): '{1}'.";
public const string IDX10223 = "IDX10223: Lifetime validation failed. The token is expired. ValidTo (UTC): '{0}', Current time (UTC): '{1}'.";
Expand Down Expand Up @@ -79,6 +79,8 @@ internal static class LogMessages
//public const string IDX10263 = "IDX10263: Unable to re-validate with ConfigurationManager.LastKnownGoodConfiguration as it is expired.";
public const string IDX10264 = "IDX10264: Reading issuer signing keys from validation parameters and configuration.";
public const string IDX10265 = "IDX10265: Reading issuer signing keys from configuration.";
//public const string IDX10266 = "IDX10266: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace, validationParameters.ValidIssuers is null or empty and ConfigurationManager is null.";


// 10500 - SignatureValidation
public const string IDX10500 = "IDX10500: Signature validation failed. No security keys were provided to validate the signature.";
Expand Down
22 changes: 3 additions & 19 deletions src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.IdentityModel.Tokens
/// <summary>
/// Contains a set of parameters that are used by a <see cref="SecurityTokenHandler"/> when validating a <see cref="SecurityToken"/>.
/// </summary>
public class TokenValidationParameters
public partial class TokenValidationParameters
{
private string _authenticationType;
private TimeSpan _clockSkew = DefaultClockSkew;
Expand All @@ -38,7 +38,7 @@ public class TokenValidationParameters
/// Default for the maximum token size.
/// </summary>
/// <remarks>250 KB (kilobytes).</remarks>
public const Int32 DefaultMaximumTokenSizeInBytes = 1024 * 250;
public const int DefaultMaximumTokenSizeInBytes = 1024 * 250;
brentschmaltz marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Copy constructor for <see cref="TokenValidationParameters"/>.
Expand Down Expand Up @@ -66,6 +66,7 @@ protected TokenValidationParameters(TokenValidationParameters other)
IssuerSigningKeyValidatorUsingConfiguration = other.IssuerSigningKeyValidatorUsingConfiguration;
IssuerValidator = other.IssuerValidator;
IssuerValidatorAsync = other.IssuerValidatorAsync;
IssuerValidationDelegateAsync = other.IssuerValidationDelegateAsync;
IssuerValidatorUsingConfiguration = other.IssuerValidatorUsingConfiguration;
LifetimeValidator = other.LifetimeValidator;
LogTokenId = other.LogTokenId;
Expand Down Expand Up @@ -172,22 +173,6 @@ public string AuthenticationType
}
}

///// <summary>
///// Gets or sets the <see cref="X509CertificateValidator"/> for validating X509Certificate2(s).
///// </summary>
//public X509CertificateValidator CertificateValidator
//{
// get
// {
// return _certificateValidator;
// }

// set
// {
// _certificateValidator = value;
// }
//}

/// <summary>
/// Gets or sets the clock skew to apply when validating a time.
/// </summary>
Expand Down Expand Up @@ -368,7 +353,6 @@ public virtual ClaimsIdentity CreateClaimsIdentity(SecurityToken securityToken,
/// </remarks>
public IssuerValidator IssuerValidator { get; set; }


/// <summary>
/// Gets or sets a delegate that will be used to validate the issuer of the token.
/// </summary>
Expand Down
81 changes: 81 additions & 0 deletions src/Microsoft.IdentityModel.Tokens/Validation/AsyncValidate.cd
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="Microsoft.IdentityModel.Tokens.TokenValidationResult" Collapsed="true">
<Position X="7.75" Y="7" Width="3.25" />
<TypeIdentifier>
<HashCode>ABEAIAABEEAAEAIAAAAAAAABEQAAAEEACABAAAAkIoA=</HashCode>
<FileName>Validation\TokenValidationResult.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Microsoft.IdentityModel.Tokens.IssuerValidationResult">
<Position X="12.5" Y="7" Width="2.25" />
<TypeIdentifier>
<HashCode>AAEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAA=</HashCode>
<FileName>Validation\IssuerValidationResult.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Microsoft.IdentityModel.Tokens.ExceptionDetail">
<Position X="6.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAEAAAAAAAAAAAAAAAAEAAEAAAAAAAAAEAABAAAAAA=</HashCode>
<FileName>Validation\ExceptionDetail.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Property Name="MessageDetail" />
</ShowAsAssociation>
</Class>
<Class Name="Microsoft.IdentityModel.Tokens.ValidationResult">
<Position X="8.5" Y="3.5" Width="3.5" />
<TypeIdentifier>
<HashCode>AIAAAAJAAAAAAAAAAAgAIAABAAgAAAAABEBBAAAAAAA=</HashCode>
<FileName>Validation\ValidationResult.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Property Name="ExceptionDetail" />
<Property Name="CallContext" />
<Property Name="ValidationFailureType" />
</ShowAsAssociation>
<ShowAsCollectionAssociation>
<Property Name="LogDetails" />
</ShowAsCollectionAssociation>
</Class>
<Class Name="Microsoft.IdentityModel.Tokens.LogDetail">
<Position X="12" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEAAA=</HashCode>
<FileName>Validation\LogDetail.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Property Name="MessageDetail" />
</ShowAsAssociation>
</Class>
<Class Name="Microsoft.IdentityModel.Tokens.ValidationFailureType" Collapsed="true">
<Position X="13.5" Y="5.5" Width="2.5" />
<Compartments>
<Compartment Name="Nested Types" Collapsed="false" />
</Compartments>
<TypeIdentifier>
<HashCode>AAAIAAAAAAAAAAAAAAIAAAQAAABAQAAAAAAAAAAAAAA=</HashCode>
<FileName>Validation\ValidationFailureType.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Microsoft.IdentityModel.Tokens.MessageDetail">
<Position X="9.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAEIAAIAAAAAA=</HashCode>
<FileName>Validation\MessageDetail.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Microsoft.IdentityModel.Tokens.CallContext" Collapsed="true">
<Position X="13.5" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>CallContext.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Microsoft.IdentityModel.Logging.LoggerContext" Collapsed="true">
<Position X="15.5" Y="4.5" Width="1.5" />
<TypeIdentifier />
</Class>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Microsoft.IdentityModel.Tokens
{
/// <summary>
/// Contains information so that Exceptions can be logged or thrown written as required.
/// </summary>
internal class ExceptionDetail
{
/// <summary>
/// Creates an instance of <see cref="ExceptionDetail"/>
/// </summary>
/// <paramref name="messageDetail"/> contains information about the exception that is used to generate the exception message.
/// <paramref name="exceptionType"/> is the type of exception that occurred.
/// <paramref name="stackFrame"/> contains information about the stack frame where the exception occurred.
public ExceptionDetail(MessageDetail messageDetail, Type exceptionType, StackFrame stackFrame)
: this(messageDetail, exceptionType, stackFrame, null)
{
}

/// <summary>
/// Creates an instance of <see cref="ExceptionDetail"/>
/// </summary>
/// <paramref name="messageDetail"/> contains information about the exception that is used to generate the exception message.
/// <paramref name="exceptionType"/> is the type of exception that occurred.
/// <paramref name="stackFrame"/> contains information about the stack frame where the exception occurred.
/// <paramref name="innerException"/> is the inner exception that occurred.
public ExceptionDetail(MessageDetail messageDetail, Type exceptionType, StackFrame stackFrame, Exception innerException)
{
ExceptionType = exceptionType;
InnerException = innerException;
MessageDetail = messageDetail;
StackFrames.Add(stackFrame);
}

/// <summary>
/// Creates an instance of an <see cref="Exception"/> using <see cref="ExceptionDetail"/>
/// </summary>
/// <returns>An instantance of an Exception.</returns>
public Exception GetException()
{
if (InnerException != null)
return Activator.CreateInstance(ExceptionType, MessageDetail.Message, InnerException) as Exception;

return Activator.CreateInstance(ExceptionType, MessageDetail.Message) as Exception;
}

/// <summary>
/// Gets the type of exception that occurred.
/// </summary>
public Type ExceptionType { get; }

/// <summary>
/// Gets the inner exception that occurred.
/// </summary>
public Exception InnerException { get; }

/// <summary>
/// Gets the message details that are used to generate the exception message.
/// </summary>
public MessageDetail MessageDetail { get; }

/// <summary>
/// Gets the stack frames where the exception occurred.
/// </summary>
public IList<StackFrame> StackFrames { get; } = [];
}
}
35 changes: 35 additions & 0 deletions src/Microsoft.IdentityModel.Tokens/Validation/Exceptions.cd
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="Microsoft.IdentityModel.Tokens.SecurityTokenException">
<Position X="6.25" Y="1.25" Width="2.5" />
<TypeIdentifier>
<HashCode>AIAAAAAAAgAAAgAAAAQAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Exceptions\SecurityTokenException.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Property Name="ExceptionDetail" />
</ShowAsAssociation>
</Class>
<Class Name="Microsoft.IdentityModel.Tokens.SecurityTokenValidationException" Collapsed="true">
<Position X="6.5" Y="4" Width="2.25" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Exceptions\SecurityTokenValidationException.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Microsoft.IdentityModel.Tokens.SecurityTokenInvalidIssuerException">
<Position X="6.25" Y="5.25" Width="2.75" />
<TypeIdentifier>
<HashCode>AAgAAEAAAAAAAAAAAAACAAAgAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Exceptions\SecurityTokenInvalidIssuerException.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Microsoft.IdentityModel.Tokens.ExceptionDetail">
<Position X="10.25" Y="1.25" Width="1.75" />
<TypeIdentifier>
<HashCode>AAAEAAAAAAAAAAAAAAAAEAAEAAAAAAAAAEAABAAAAAA=</HashCode>
<FileName>Validation\ExceptionDetail.cs</FileName>
</TypeIdentifier>
</Class>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>
Loading
Loading