Skip to content

License validation: clear messages for malformed keys, client platforms, and IdentityModel version mismatches - #4670

Merged
jbogard merged 10 commits into
mainfrom
license-key-diagnostics
Oct 27, 2026
Merged

jbogard merged 10 commits into
mainfrom
license-key-diagnostics

Conversation

@jbogard

@jbogard jbogard commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Fixes #4661
Fixes #4662
Part of #4659 (whitespace stripping is #4663)

Most license support cases show IDX10511: Signature validation failed at 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

  • Truncated or malformed keys (Detect truncated or malformed license keys and log a clear message #4661): before validating, the key is checked for three base64url segments and a 342-character RS256 signature. A key that fails gets an ERROR-level "incomplete or corrupted… copy the full key again" message, and the key is never logged.
  • Client platforms (Blazor WASM: PlatformNotSupportedException inside the validation result is logged as a critical signature error #4662): checks whether RSA is available before validating. If it isn't, as on Blazor WASM, it logs the existing INFO client-redistribution message instead of a critical signature error.
  • No IDX exceptions at default log levels: each validation failure logs a plain CRITICAL message, and the exception goes to Debug for support. The failures covered are invalid signature, undecodable token, wrong issuer/audience, and mismatched Microsoft.IdentityModel.* package versions (IDX14102 wrapping MissingMethodException, seen in support on MAUI).
  • Links go through https://luckypennysoftware.com/go/automapper-* redirects, so they can be repointed after release.
  • Docs: License-configuration.md gets 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 PlatformNotSupportedException by walking InnerException. In IdentityModel 8.14, JsonWebTokenHandler.ValidateSignature catches 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() throws PlatformNotSupportedException
  • The validation result's exception is a single SecurityTokenInvalidSignatureException with no inner exception

So this PR checks RSA directly. The inner-exception walk and the catch are kept as a backup.

Before (main), Blazor WASM console:

crit: LuckyPennySoftware.AutoMapper.License[0]
      Error validating the Lucky Penny software license key
SecurityTokenInvalidSignatureException: IDX10511: Signature validation failed. ...
Exceptions caught: '[PII of type 'System.Text.StringBuilder' is hidden ...]'

After:

info: LuckyPennySoftware.AutoMapper.License[0]
      RSA cryptography is not supported on this platform. For client redistribution scenarios such as Blazor WASM, see: <link>

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

🤖 Generated with Claude Code

jbogard and others added 5 commits October 26, 2026 17:53
…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>
Copilot AI balanced review requested due to automatic review settings October 27, 2026 13:58
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-27T19:57:57.923475Z 5990ce2 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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

Comment on lines +127 to 128
LogPlatformNotSupported();
return [];
jbogard and others added 5 commits October 27, 2026 14:39
# 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>
@jbogard
jbogard merged commit abeda24 into main Oct 27, 2026
6 checks passed
@jbogard
jbogard deleted the license-key-diagnostics branch October 27, 2026 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants