Skip to content
Merged
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
57 changes: 34 additions & 23 deletions src/AutoMapper/Licensing/LicenseAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,35 +47,46 @@ private License Initialize()

private Claim[] ValidateKey(string licenseKey)
{
var handler = new JsonWebTokenHandler();

var rsa = new RSAParameters
try
{
Exponent = Convert.FromBase64String("AQAB"),
Modulus = Convert.FromBase64String(
"2LTtdJV2b0mYoRqChRCfcqnbpKvsiCcDYwJ+qPtvQXWXozOhGo02/V0SWMFBdbZHUzpEytIiEcojo7Vbq5mQmt4lg92auyPKsWq6qSmCVZCUuL/kpYqLCit4yUC0YqZfw4H9zLf1yAIOgyXQf1x6g+kscDo1pWAniSl9a9l/LXRVEnGz+OfeUrN/5gzpracGUY6phx6T09UCRuzi4YqqO4VJzL877W0jCW2Q7jMzHxOK04VSjNc22CADuCd34mrFs23R0vVm1DVLYtPGD76/rGOcxO6vmRc7ydBAvt1IoUsrY0vQ2rahp51YPxqqhKPd8nNOomHWblCCA7YUeV3C1Q==")
};
var handler = new JsonWebTokenHandler();

var key = new RsaSecurityKey(rsa)
{
KeyId = "LuckyPennySoftwareLicenseKey/bbb13acb59904d89b4cb1c85f088ccf9"
};
var rsa = new RSAParameters
{
Exponent = Convert.FromBase64String("AQAB"),
Modulus = Convert.FromBase64String(
"2LTtdJV2b0mYoRqChRCfcqnbpKvsiCcDYwJ+qPtvQXWXozOhGo02/V0SWMFBdbZHUzpEytIiEcojo7Vbq5mQmt4lg92auyPKsWq6qSmCVZCUuL/kpYqLCit4yUC0YqZfw4H9zLf1yAIOgyXQf1x6g+kscDo1pWAniSl9a9l/LXRVEnGz+OfeUrN/5gzpracGUY6phx6T09UCRuzi4YqqO4VJzL877W0jCW2Q7jMzHxOK04VSjNc22CADuCd34mrFs23R0vVm1DVLYtPGD76/rGOcxO6vmRc7ydBAvt1IoUsrY0vQ2rahp51YPxqqhKPd8nNOomHWblCCA7YUeV3C1Q==")
};

var parms = new TokenValidationParameters
{
ValidIssuer = "https://luckypennysoftware.com",
ValidAudience = "LuckyPennySoftware",
IssuerSigningKey = key,
ValidateLifetime = false
};
var key = new RsaSecurityKey(rsa)
{
KeyId = "LuckyPennySoftwareLicenseKey/bbb13acb59904d89b4cb1c85f088ccf9"
};

var parms = new TokenValidationParameters
{
ValidIssuer = "https://luckypennysoftware.com",
ValidAudience = "LuckyPennySoftware",
IssuerSigningKey = key,
ValidateLifetime = false
};

var validateResult = handler.ValidateTokenAsync(licenseKey, parms).Result;
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

Using .Result on an async method can cause deadlocks in certain synchronization contexts and wraps exceptions in AggregateException. Since the handler.ValidateTokenAsync call might throw exceptions synchronously (before returning a Task), those exceptions may be wrapped in AggregateException when accessing .Result. This could complicate exception handling. Consider using GetAwaiter().GetResult() instead, which unwraps the exception, or making this method async and using await.

Suggested change
var validateResult = handler.ValidateTokenAsync(licenseKey, parms).Result;
var validateResult = handler.ValidateTokenAsync(licenseKey, parms).GetAwaiter().GetResult();

Copilot uses AI. Check for mistakes.
if (!validateResult.IsValid)
{
_logger.LogCritical(validateResult.Exception, "Error validating the Lucky Penny software license key");
}

var validateResult = handler.ValidateTokenAsync(licenseKey, parms).Result;
if (!validateResult.IsValid)
return validateResult.ClaimsIdentity?.Claims.ToArray() ?? [];
}
catch (PlatformNotSupportedException)
{
_logger.LogCritical(validateResult.Exception, "Error validating the Lucky Penny software license key");
_logger.LogInformation(
"RSA cryptography is not supported on this platform. " +
"For client redistribution scenarios such as Blazor WASM, see: " +
"https://docs.automapper.io/en/latest/License-configuration.html#client-redistribution-scenarios");
return [];
}
Comment on lines +82 to 89
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

The PR description states it fixes issue #4592 which asks for better exception messages for JWT validation errors (specifically ArgumentException and FormatException like "IDX14101: Unable to decode the payload"). However, the code changes only add a try-catch for PlatformNotSupportedException, which is a different scenario (unsupported cryptography on certain platforms like Blazor WASM). The original issue's JWT decoding errors would still not be caught or given better messages by this implementation.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

The PR description states this fixes issue #4592, which mentions catching exceptions like ArgumentException and FormatException during JWT validation to provide better error messages. However, the current implementation only catches PlatformNotSupportedException. The ArgumentException and FormatException shown in the issue (IDX14101, IDX10400) would not be caught by this try-catch block. Consider adding a catch block for these exceptions (or a more general exception type) that logs a user-friendly message like "The provided license key is invalid or malformed. Please check that you have copied the entire license key correctly."

Suggested change
}
}
catch (ArgumentException ex)
{
_logger.LogWarning(ex,
"The provided license key is invalid or malformed. Please check that you have copied the entire license key correctly.");
return [];
}
catch (FormatException ex)
{
_logger.LogWarning(ex,
"The provided license key is invalid or malformed. Please check that you have copied the entire license key correctly.");
return [];
}

Copilot uses AI. Check for mistakes.

return validateResult.ClaimsIdentity?.Claims.ToArray() ?? [];
}

}