Repository navigation
License validation: clear messages for malformed keys, client platforms, and IdentityModel version mismatches - #4670
Conversation
…forms - Check the key's structure (three base64url segments, 342-character RS256 signature) before validating, and log an error-level "incomplete or corrupted" message instead of an IDX signature error (#4661). The key is never logged. - Add a copy/paste hint when validation fails with an invalid signature. - Detect client platforms without RSA support, such as Blazor WASM (#4662). JsonWebTokenHandler swallows the PlatformNotSupportedException and reports IDX10511, with the original exception only as PII-hidden message text, so probe RSA directly before validating. Also walk the result's exception chain for a PlatformNotSupportedException. Fixes #4661 Fixes #4662 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…debug IDX exceptions aren't actionable for customers, and with PII logging off they hide most details anyway. Log one plain critical message per failure kind (invalid signature, undecodable token, wrong issuer/audience, other) without the exception, and log the exception at debug level for support. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mixed Microsoft.IdentityModel.* package versions surface as IDX14102 wrapping a MissingMethodException (seen in support on MAUI). Report that as a package version problem rather than a corrupted key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shipped binaries live for years, so link to redirects we control (license key, client platforms, IdentityModel versions) instead of docs URLs that have already moved once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Document the new validation messages (incomplete/corrupted key, signature mismatch, not a Lucky Penny key, mismatched Microsoft.IdentityModel versions), the client-platform INFO message, and how to see the underlying exception at Debug level. These sections are the targets of the /go redirects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 252803384a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| The key is missing characters or contains characters that aren't part of a license key. This usually happens when the key is copied from a PDF or an email, where it can be truncated or wrapped across lines. | ||
|
|
||
| AutoMapper removes whitespace (spaces, tabs, and line breaks) from the key before validating it, so line breaks and trailing newlines, such as those in Kubernetes secrets created from files, are not a problem. Missing characters can't be recovered: copy the full key again from your [account page](https://luckypennysoftware.com/account). |
There was a problem hiding this comment.
Align whitespace troubleshooting advice with the implemented behavior
For keys containing line breaks or a trailing newline, the documented behavior does not match this commit: ResolveLicenseKey returns the configured value unchanged, and IsWellFormed rejects every whitespace character before validation. A valid key loaded from the Kubernetes secret described here therefore still produces the incomplete-or-corrupted error, while this guidance incorrectly rules out the cause. Include the whitespace-normalization dependency before publishing this claim, or document that whitespace must currently be removed by the caller.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
🟡 Changes recommended
Unsupported-platform handling still triggers a downstream missing-license warning instead of the intended informational-only message.
1 open issue
What changed in this PR
This PR improves AutoMapper’s license-validation diagnostics for malformed keys, unsupported client platforms, and IdentityModel package mismatches.
Changes:
- Adds structural key checks and an RSA availability probe.
- Replaces customer-facing exception details with actionable messages and support links, retaining details at Debug level.
- Adds diagnostic tests and troubleshooting documentation; merging remains dependent on #4663 and redirect deployment.
| File | Description |
|---|---|
| src/UnitTests/Licensing/LicenseAccessorTests.cs | Tests malformed keys, failure classification, and logging behavior. |
| src/AutoMapper/Licensing/LicenseAccessor.cs | Adds key checks, platform detection, and clearer validation messages. |
| docs/source/License-configuration.md | Documents troubleshooting, log levels, and client-platform behavior. |
Review effort: Balanced
| LogPlatformNotSupported(); | ||
| return []; |
# Conflicts: # src/AutoMapper/Licensing/LicenseAccessor.cs
- When license keys can't be validated on this platform (no RSA, e.g. Blazor WASM), mark the license as validation-unsupported so the validator skips the "no valid license key" warning after the INFO client-platform message. - Rename LicenseKeyLink to AccountPageLink: CodeQL's name heuristic flagged the URL constant as sensitive data. - Include the debug-level exception in the test failure message for the plain-critical assertions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pply The test host's AppDomain doesn't use AutoMapper.UnitTests.dll.config, so redirects such as System.Threading.Tasks.Extensions were ignored and license validation failed to load them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…vered With xunit.appDomain=ifAvailable the net471 run reports "No test is available" and passes with zero tests. Back to skipping the end-to-end invalid signature test on .NET Framework. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Updated [AutoMapper](https://github.com/LuckyPennySoftware/AutoMapper) from 16.2.0 to 16.3.0. <details> <summary>Release notes</summary> _Sourced from [AutoMapper's releases](https://github.com/LuckyPennySoftware/AutoMapper/releases)._ ## 16.3.0 ## Security This release fixes two denial-of-service vulnerabilities. In both, deeply nested input could bypass `MaxDepth` and exhaust the stack. The resulting `StackOverflowException` can't be caught, so it ends the process. Please upgrade if your application maps untrusted, deeply nested data. - [GHSA-6vhm-j9h7-f9gh](GHSA-6vhm-j9h7-f9gh): `MaxDepth` wasn't enforced when mapping through constructor parameters, including positional records. Thanks to @mcambria for the report. - [GHSA-gpwp-5797-mjff](GHSA-gpwp-5797-mjff): other recursion paths bypassed `MaxDepth`: derived maps, `object` and interface members, dictionary and dynamic sources, and recursive type converters. CVE IDs have been requested and will be added here once they're assigned. ## Behavior changes - Recursion that `MaxDepth` can't limit now throws a catchable `InsufficientExecutionStackException` instead of crashing the process. - Derived maps (`Include` / `IncludeBase`) now inherit `MaxDepth` and get the default limit of 64 for self-referential maps. If your polymorphic graphs legitimately go deeper, set `MaxDepth` explicitly. - Constructor mapping now stops at the same depth as property mapping. - `Condition` on `ForAllMembers`, or any condition whose member parameter is `object` or a base type, now receives the source member value instead of the value converted to the destination type, when those types differ. This matches the documented contract. A `null` in a nullable source member is now seen as `null` rather than `0` or `false` (#4655). ## Other highlights - Fixed `Context.Items are only available...` exceptions with `MaxDepth`, which depended on registration or warmup order (#4651) - License keys get a 30-day renewal grace period, which logs a warning instead of an error (#4667) - Clearer license validation messages for malformed keys, client platforms and IdentityModel version mismatches (#4670) - Whitespace is stripped from license keys (#4663), and license validation is isolated from the host app's `CryptoProviderFactory` (#4674) - ## What's Changed * Bump Testcontainers.MsSql to 4.14.0 to clear NU1903 by @jbogard in LuckyPennySoftware/AutoMapper#4652 * docs: replace dead MyGet build link with CI feed link by @JiuYue0820 in LuckyPennySoftware/AutoMapper#4648 * Emit the context check for the containing type map in CollectionMapper (fixes #4650) by @jbogard in LuckyPennySoftware/AutoMapper#4651 * Pass the source member value to Condition by @jbogard in LuckyPennySoftware/AutoMapper#4655 * Fix licensing page structure in docs ToC by @jbogard in LuckyPennySoftware/AutoMapper#4664 * Fix BuildDateUtc embedding on Windows builds by @jbogard in LuckyPennySoftware/AutoMapper#4666 * License validation: WARNING during the renewal grace period by @jbogard in LuckyPennySoftware/AutoMapper#4667 * Fail the release when the tag is not on its release branch by @jbogard in LuckyPennySoftware/AutoMapper#4668 * ci: bump lock-threads to v6 to fix token validation failure by @simpleqt in LuckyPennySoftware/AutoMapper#4658 * Strip whitespace from license keys before resolving precedence by @AVTUNEY in LuckyPennySoftware/AutoMapper#4663 * License validation: clear messages for malformed keys, client platforms, and IdentityModel version mismatches by @jbogard in LuckyPennySoftware/AutoMapper#4670 * Move to central package management by @jbogard in LuckyPennySoftware/AutoMapper#4672 * License validation: isolate from the host app's CryptoProviderFactory by @jbogard in LuckyPennySoftware/AutoMapper#4674 * Replace broken ApiCompat setup with SDK package validation by @jbogard in LuckyPennySoftware/AutoMapper#4673 * Add regression test for registration-order MaxDepth context failure by @jbogard in LuckyPennySoftware/AutoMapper#4675 * Document license key environment variables in the README by @jbogard in LuckyPennySoftware/AutoMapper#4677 ## New Contributors * @JiuYue0820 made their first contribution in LuckyPennySoftware/AutoMapper#4648 * @simpleqt made their first contribution in LuckyPennySoftware/AutoMapper#4658 * @AVTUNEY made their first contribution in LuckyPennySoftware/AutoMapper#4663 **Full Changelog**: LuckyPennySoftware/AutoMapper@v16.2.0...v16.3.0 Commits viewable in [compare view](LuckyPennySoftware/AutoMapper@v16.2.0...v16.3.0). </details> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/sondresjolyst/garge-api/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

Fixes #4661
Fixes #4662
Part of #4659 (whitespace stripping is #4663)
Most license support cases show
IDX10511: Signature validation failedat critical level, even when the key itself is fine. This PR replaces the IdentityModel exceptions in customer-facing logs with one plain message per failure, each with a link that says what to do.Changes
Debugfor support. The failures covered are invalid signature, undecodable token, wrong issuer/audience, and mismatchedMicrosoft.IdentityModel.*package versions (IDX14102 wrappingMissingMethodException, seen in support on MAUI).https://luckypennysoftware.com/go/automapper-*redirects, so they can be repointed after release.License-configuration.mdgets a "Troubleshooting License Key Validation" section, an updated log-level list, and a client-platform note.Why #4662's proposed fix doesn't work
The issue proposed finding
PlatformNotSupportedExceptionby walkingInnerException. In IdentityModel 8.14,JsonWebTokenHandler.ValidateSignaturecatches it and turns it into a string inside the IDX10511 message, and by default that string is hidden as PII. Verified in Blazor WASM (.NET 10, Chrome):RSA.Create()throwsPlatformNotSupportedExceptionSecurityTokenInvalidSignatureExceptionwith no inner exceptionSo this PR checks RSA directly. The inner-exception walk and the
catchare kept as a backup.Before (main), Blazor WASM console:
After:
Tests
There's no real test license key, so the tests build a key with the right structure and a bogus signature. They cover truncation (1/5/20 characters), wrong segment counts, invalid characters, the invalid-signature path, an undecodable header, nested/aggregated
PlatformNotSupportedException, IdentityModel version mismatch, and wrong issuer/audience. They also assert that no critical message carries an exception or "IDX". Full unit suite: 1,253 passed. Docs build with no new warnings.Before merging
/go/automapper-*redirects live (LuckyPennySoftware/Website#395)LicenseAccessor.csis expected🤖 Generated with Claude Code