Repository navigation
Conversation
- Retarget JwtValidator to net10.0 - Bump System.IdentityModel.Tokens.Jwt 7.6.0 -> 8.23.0 - Fix typo in project description - Stop tracking JwtValidator.csproj.user and broaden .gitignore Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…odes Bug fixes: - JWKS with several RSA keys: every key was imported into one shared RSA instance, so only the last RSA key was ever used. Keys are now loaded with JsonWebKeySet and passed as IssuerSigningKeys, so kid is honoured. - EC (ES256/384/512) and PS* tokens are supported instead of RS256 only. - JWT read from --jwt-file is trimmed; a trailing newline made it unreadable. - Replace sync-over-async HttpClient .Result with async Main and dispose it. - Replace legacy RSACryptoServiceProvider with RSA.Create(). - Manual validation no longer returns an undisposed SHA256; supports RS256/384/512 and picks the key by kid. - Fix all nullable warnings; enable TreatWarningsAsErrors. Changes: - Switch from JwtSecurityTokenHandler to JsonWebTokenHandler (Microsoft.IdentityModel.JsonWebTokens 8.23.0) and drop Newtonsoft.Json. - Split Program.cs into Options, KeyLoader, TokenValidator, TokenDiagnostics and ValidateCommand. - Diagnostics: decoded header/claims, iat/nbf/exp as UTC with expired/not-yet-valid status, key set summary, kid mismatch warning, and a readable failure reason (full detail with --verbose). - New options: --issuer, --audience, --validate-lifetime, --clock-skew. - Exit codes: 0 valid, 1 invalid token, 2 usage or input error. --help and --version exit 0. - Reject ambiguous input (both --jwt and --jwt-file, or several key sources). - Add .editorconfig. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Move JwtValidator to src/JwtValidator - Replace JwtValidator.sln with JwtValidator.slnx (dotnet sln migrate), with src/ and tests/ solution folders and the repo files as solution items - Move shared build settings (TFM, nullable, warnings as errors, code style enforcement) into Directory.Build.props Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- tests/JwtValidator.Tests (xUnit v3 on Microsoft.Testing.Platform): 56 tests that sign tokens with RSA/EC keys generated in memory and cover PEM and JWKS keys, the multi-key JWKS regression, ES256/384/512, PS256, wrong key, tampered payload, unsigned tokens, lifetime, issuer and audience checks, manual validation, diagnostics output, option validation and end-to-end exit codes (including JWKS over HTTP). - global.json opts in to the Microsoft.Testing.Platform dotnet test mode. - .github/workflows/build.yml builds and tests on push/PR to main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Add /// documentation to every method and type in src and tests - Enable GenerateDocumentationFile so doc comments (including crefs) are checked by the compiler, with warnings as errors - Bump xunit.v3 4.0.1 -> 4.0.2 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
A malformed JWKS throws InvalidDataException, which escapes ValidateCommand's catch filter and crashes the process instead of returning the documented exit code 2.
1 open finding
What changed in this PR
This PR modernizes the JwtValidator CLI troubleshooting tool. It upgrades the target framework from .NET 8 to .NET 10, replaces the deprecated JwtSecurityTokenHandler/Newtonsoft.Json stack with JsonWebTokenHandler (Microsoft.IdentityModel.JsonWebTokens 8.23.0), and restructures the single Program.cs into focused types (Options, KeyLoader, TokenValidator, TokenDiagnostics, ValidateCommand, ExitCodes). It fixes several real validation bugs (notably JWKS multi-key handling that previously only used the last RSA key, trailing-newline handling in --jwt-file, EC key support, and undisposed crypto/HTTP resources), adds rich diagnostics output, opt-in claim checks, process exit codes, a src/ + tests/ layout with a .slnx solution, a comprehensive xUnit v3 test suite, and a GitHub Actions CI workflow.
Changes:
- Upgrade to .NET 10 and switch to
JsonWebTokenHandler; load JWKS viaJsonWebKeySetwithkid-aware matching and support for RS/PS/ES 256/384/512. - Split
Program.csinto cohesive components, add diagnostics, new claim-check options, and standardized exit codes (0/1/2). - Introduce repository restructure (
src/,tests/,.slnx,Directory.Build.props,.editorconfig,global.json), unit tests, and a CI build/test workflow.
| File | Description |
|---|---|
| src/JwtValidator/ValidateCommand.cs | Orchestrates read/load/validate and maps outcomes to exit codes; catch filter omits InvalidDataException. |
| src/JwtValidator/KeyLoader.cs | Loads keys from PEM/JWKS (URL/file/JSON); describes every JWKS entry; RSA parameter extraction. |
| src/JwtValidator/TokenValidator.cs | Builds validation parameters and performs handler-based and manual RSA signature validation. |
| src/JwtValidator/TokenDiagnostics.cs | Renders human-readable token/key diagnostics, time humanization, and lifetime notes. |
| src/JwtValidator/Options.cs | CLI options plus usage-error validation for token/key source combinations and clock skew. |
| src/JwtValidator/Program.cs | Entry point: arg parsing, help/version handling, usage errors, and command dispatch. |
| src/JwtValidator/ExitCodes.cs | Centralizes 0/1/2 exit-code constants. |
| src/JwtValidator/JwtValidator.csproj | Targets new package set, adds InternalsVisibleTo for tests. |
| src/JwtValidator/Properties/launchSettings.json | Dev launch profiles (sample tokens/JWKS, some stale). |
| tests/JwtValidator.Tests/*.cs | xUnit v3 tests for options, key loading, validation, diagnostics, and the command. |
| tests/JwtValidator.Tests/JwtValidator.Tests.csproj | Test project referencing xunit.v3 and the main project. |
| Directory.Build.props / global.json / .editorconfig | Shared build settings, SDK/test-runner pinning, and style rules. |
| JwtValidator.slnx / JwtValidator.sln | Migrates to the .slnx solution format. |
| .github/workflows/build.yml | CI build and test on push/PR to main. |
| README.md / .gitignore | Rewritten usage docs; broader ignore rules; untracks *.user. |
| JwtValidator/Program.cs, *.csproj.user | Removes the old flat-layout source and tracked user file. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or HttpRequestException | ||
| or TaskCanceledException or ArgumentException or JsonException) |

Summary
Upgrades JwtValidator to .NET 10 and fixes several validation bugs, including one where JWKS validation used the wrong key. It also adds better diagnostics, opt-in claim checks, exit codes, unit tests and a CI build. The repo moves to a
src/+tests/layout with a.slnxsolution.Bug fixes
RSAinstance, so each key overwrote the previous one andkidwas ignored. Tokens signed by any other key in the set failed. Keys are now loaded withJsonWebKeySetand matched bykid, with a fallback that tries every key. There is a regression test.--jwt-filedidn't work with a trailing newline, which most files have; the token was reported as malformed. Input is now trimmed.HttpClient...Resultwith an undisposed client; legacyRSACryptoServiceProvider; manual validation returned an undisposedSHA256.Changes
net10.0, withJwtSecurityTokenHandlerreplaced byJsonWebTokenHandler(Microsoft.IdentityModel.JsonWebTokens8.23.0) andNewtonsoft.Jsondropped.src/JwtValidator,tests/JwtValidator.Tests,JwtValidator.slnx(migrated from.sln), a sharedDirectory.Build.props,.editorconfigandglobal.json.Program.csis split intoOptions,KeyLoader,TokenValidator,TokenDiagnosticsandValidateCommand.iat/nbf/expas UTC with expired/not-yet-valid status. It lists the key set, warns about unusable JWKS entries and akidthat isn't in the set, and gives a one-line failure reason (--verboseadds the full payload and error detail).--issuer,--audience,--validate-lifetime,--clock-skew. All are off by default, so existing usage behaves the same.0valid,1invalid token,2usage or input error.--jwtand--jwt-file, or more than one key source, is now a usage error. Previously one of them was silently ignored.main.JwtValidator.csproj.useris no longer tracked.GenerateDocumentationFilemakes the compiler check them.Testing
dotnet test --solution JwtValidator.slnx: 56/56 pass. Tests sign tokens with RSA/EC keys generated in memory, so no key material is committed.--help/--versionexit 0; missing or conflicting options exit 2; a missing file exits 2.jwks filelaunch-profile token validates against the live--jwks-urland reports the matching kid.good key/bad key/key2launch-profile tokens don't validate against their inline JWKS. The original code onmainrejects them too, so that's stale sample data, not a regression.🤖 Generated with Claude Code