Release v2.2 - Custom JWT Implementation#41
Merged
kirill-abblix merged 40 commits intomasterfrom Feb 18, 2026
Merged
Conversation
Add missing Authentication Method Reference (AMR) values from RFC 8176: - bio: Generic biometric authentication - oob: Out-of-band authentication - x509: X.509 certificate-based authentication These standardized AMR values complete the implementation of RFC 8176 and enable proper authentication method reporting in ID tokens.
Introduce IAcrMetadataProvider interface and default implementation to support configurable ACR (Authentication Context Class Reference) values. The provider pattern allows extensibility while the default implementation reads values from DiscoveryOptions configuration. This enables dynamic ACR values based on deployment environment or custom authentication policies.
Add support for acr_values_supported metadata in OpenID Connect discovery document as defined in OpenID Connect Discovery 1.0 specification. The discovery document now includes ACR values when configured, allowing clients to discover supported authentication assurance levels. Integration uses the IAcrMetadataProvider to retrieve configured values. Changes: - Add AcrValuesSupported property to ConfigurationResponse models - Update ConfigurationHandler to populate ACR values from provider - Update ConfigurationResponseFormatter to serialize ACR values to JSON
…ance Remove non-standard Authentication Method Reference (AMR) values that are not present in the IANA registry or RFC 8176 specification. Comment out "bio", "oob", and "x509" constants with detailed explanations of why they are non-compliant and what standard alternatives should be used instead. The "oob" (out-of-band) identifier is used in OAuth for deprecated redirect URIs, not as an AMR value. RFC 8176 defines "sms" and "tel" for out-of-band methods. The generic "bio" should be replaced with specific biometric values like "face", "fpt", "iris", "retina", or "vbm". The "x509" should use "sc" (SmartCard) for certificate-based authentication per RFC 8176. This change improves standards compliance and provides clear migration guidance for developers using these values.
Allow clients to provide JWKS for encryption and request signing regardless of authentication method. Public clients and client_secret_* clients may use JWKS for ID token encryption, UserInfo encryption, and request object signing. This aligns with OIDC Dynamic Client Registration specification. - Remove restriction preventing public clients from having JWKS - Remove restriction preventing client_secret_basic/post clients from having JWKS - Fix TLS authentication validation (tls_client_auth requires TLS metadata, self_signed_tls_client_auth can use JWKS) - Update documentation explaining JWKS usage for encryption and signing
Fixes ObjectDisposedException when HttpClient disposes the shared singleton handler. Changed from AddSingleton to AddTransient to ensure each HTTP client gets its own handler instance that can be safely disposed. Issue: 'upstream sent too big header' errors during Implicit Flow requests due to disposed message handler causing 502 Bad Gateway responses.
…ntation (#39) * feat: add missing RFC 8176 AMR values Add missing Authentication Method Reference (AMR) values from RFC 8176: - bio: Generic biometric authentication - oob: Out-of-band authentication - x509: X.509 certificate-based authentication These standardized AMR values complete the implementation of RFC 8176 and enable proper authentication method reporting in ID tokens. * feat: add IAcrMetadataProvider for ACR values configuration Introduce IAcrMetadataProvider interface and default implementation to support configurable ACR (Authentication Context Class Reference) values. The provider pattern allows extensibility while the default implementation reads values from DiscoveryOptions configuration. This enables dynamic ACR values based on deployment environment or custom authentication policies. * feat: add acr_values_supported to OpenID discovery document Add support for acr_values_supported metadata in OpenID Connect discovery document as defined in OpenID Connect Discovery 1.0 specification. The discovery document now includes ACR values when configured, allowing clients to discover supported authentication assurance levels. Integration uses the IAcrMetadataProvider to retrieve configured values. Changes: - Add AcrValuesSupported property to ConfigurationResponse models - Update ConfigurationHandler to populate ACR values from provider - Update ConfigurationResponseFormatter to serialize ACR values to JSON * refactor: remove non-standard AMR values and document RFC 8176 compliance Remove non-standard Authentication Method Reference (AMR) values that are not present in the IANA registry or RFC 8176 specification. Comment out "bio", "oob", and "x509" constants with detailed explanations of why they are non-compliant and what standard alternatives should be used instead. The "oob" (out-of-band) identifier is used in OAuth for deprecated redirect URIs, not as an AMR value. RFC 8176 defines "sms" and "tel" for out-of-band methods. The generic "bio" should be replaced with specific biometric values like "face", "fpt", "iris", "retina", or "vbm". The "x509" should use "sc" (SmartCard) for certificate-based authentication per RFC 8176. This change improves standards compliance and provides clear migration guidance for developers using these values. * Fix dynamic client registration JWKS validation Allow clients to provide JWKS for encryption and request signing regardless of authentication method. Public clients and client_secret_* clients may use JWKS for ID token encryption, UserInfo encryption, and request object signing. This aligns with OIDC Dynamic Client Registration specification. - Remove restriction preventing public clients from having JWKS - Remove restriction preventing client_secret_basic/post clients from having JWKS - Fix TLS authentication validation (tls_client_auth requires TLS metadata, self_signed_tls_client_auth can use JWKS) - Update documentation explaining JWKS usage for encryption and signing * fix: accept JWTs with missing exp/nbf claims in lifetime validation Modified JsonWebTokenValidator to use custom LifetimeValidator that validates exp/nbf claims when present but allows them to be missing. This is required for OpenID Connect request objects which may not include expiration times. Per OIDC spec, request objects are one-time use and bound to authorization requests, making lifetime claims optional. The validator still properly validates exp/nbf when present to reject expired or not-yet-valid tokens. Added TimeProvider parameter to JsonWebTokenValidator constructor for testability and consistent time handling in validation. * fix: accept client JWTs without issuer claim for OIDC certification Modified ClientJwtValidator to support client identification via client_id claim when issuer claim is missing. This addresses OpenID Connect certification test requirements where request objects may omit the issuer claim. Client identification now follows this priority: 1. If issuer present: validate and use it to find client 2. If client_id claim present: use it to find client 3. If both present: validate they match the same client 4. If neither present: fail validation RequestObjectFetcher now validates issuer when present (but accepts missing issuer) to ensure proper client authentication while supporting flexible JWT formats required by OIDC certification tests. * refactor: simplify error handling and improve code clarity Simplified RequestObjectFetchAdapter by using Result.MapFailure instead of explicit pattern matching. Enhanced documentation for authorization request fetching workflow. Updated related components for consistency and improved readability. * feat: add byte array concatenation and base64url error handling Add utility methods for JWT implementation: - ArrayExtensions.Concat for combining byte arrays in encryption/signing operations - Enhanced Base64UrlTextEncoderConverter error handling for malformed JWT tokens These utilities provide foundation for custom JWT processing. * refactor: remove Microsoft.IdentityModel.Tokens from production code Implement complete custom JWT signing and encryption infrastructure to eliminate Microsoft.IdentityModel.Tokens dependency from Abblix.Jwt library. Key changes: - Add custom JWT signing for RSA, ECDSA, and HMAC algorithms (RFC 7515) - Add custom JWT encryption for RSA-OAEP, AES-GCM, and direct key agreement (RFC 7516) - Create EllipticCurveTypes constants for EC cryptography - Reorganize JWK types into JsonWebKeys subfolder - Add DirectKeyAgreement constructor with algorithm validation - Remove Microsoft.IdentityModel.Tokens package from Abblix.Jwt.csproj - Update OIDC Server to use custom JWT implementation - Add Microsoft interoperability tests (179 tests passing) - Keep Microsoft.IdentityModel.Tokens in test project for validation Benefits: - Broader algorithm support (RSA-OAEP-256, AES-GCM with RSA) - Full control over JWT implementation - Zero production dependency on Microsoft libraries - 100% RFC 7515/7516 compliant * refactor: redesign ValidationOptions with composite flags for clarity Introduces composite ValidationOptions flags that combine "require" and "validate" semantics into more intuitive single flags: - RequireValidIssuer (RequireIssuer | ValidateIssuer) - RequireValidAudience (RequireAudience | ValidateAudience) - RequireValidSignedTokens (RequireSignedTokens | ValidateIssuerSigningKey) This makes the API clearer while maintaining backward compatibility through bitwise operations. Default validation remains comprehensive but now uses composite flags for better maintainability. * fix: improve JWT validation logic and exception handling Enhances JWT validation by properly handling flag combinations and adding exception handling for malformed tokens: - Fixed signature validation to check both RequireSignedTokens and ValidateIssuerSigningKey flags - Fixed issuer/audience validation to respect both "require" and "validate" flags independently - Added JsonException handling in TryParseJsonObject to prevent crashes on malformed JWT JSON - Simplified JwtBearerGrantHandler to use ValidationOptions.Default These changes make validation more accurate and resilient to invalid input. * feat: enhance signing key selection with RFC 7517 fallback logic Improves JsonWebKeyExtensions.FirstByAlgorithmAsync to prioritize exact algorithm matches while falling back to algorithm-agnostic keys per RFC 7517, which allows keys without 'alg' parameter to be used with any compatible algorithm. Also adds clear error messages when no suitable signing key is found, helping developers quickly identify configuration issues. * chore: improve code quality and test infrastructure - Make EllipticCurveOids and EllipticCurveTypes public for external use - Simplify LicenseCollection with primary constructor syntax - Streamline LicenseFixture by removing redundant field manipulation - Add License collection to ClientIdValidatorTests for proper isolation - Simplify ClientInfoBuilder initialization * chore: upgrade Microsoft packages to 10.0.1 Update Microsoft.Extensions and related packages from 10.0.0 to 10.0.1 for latest bug fixes and improvements. * fix: handle JsonValue<T> types in session claim serialization Fixes InvalidOperationException when serializing JsonValue<string> instances to claims during session sign-in. The bug occurred when processing external ID tokens with custom claims during OpenID certification testing. Changes: - Renamed SerializeJsonValue to CreateClaim, returns Claim directly - Use TryGetValue<T>() pattern instead of GetValue<JsonElement>() - Added support for int, float, decimal, DateTime, DateTimeOffset - Fixed TryParseJsonValue to use claim.ValueType for type preservation - Added comprehensive unit tests (6 tests, all passing) - Converted IsStandardClaim to pattern matching with 'or' operator The fix ensures round-trip type preservation: sign-in → serialize claims → sign-out → deserialize claims → sign-in maintains exact types. Discovered during oidcc-idtoken-unsigned certification test when processing external unsigned ID token with custom claims.
* feat: add missing RFC 8176 AMR values Add missing Authentication Method Reference (AMR) values from RFC 8176: - bio: Generic biometric authentication - oob: Out-of-band authentication - x509: X.509 certificate-based authentication These standardized AMR values complete the implementation of RFC 8176 and enable proper authentication method reporting in ID tokens. * feat: add IAcrMetadataProvider for ACR values configuration Introduce IAcrMetadataProvider interface and default implementation to support configurable ACR (Authentication Context Class Reference) values. The provider pattern allows extensibility while the default implementation reads values from DiscoveryOptions configuration. This enables dynamic ACR values based on deployment environment or custom authentication policies. * feat: add acr_values_supported to OpenID discovery document Add support for acr_values_supported metadata in OpenID Connect discovery document as defined in OpenID Connect Discovery 1.0 specification. The discovery document now includes ACR values when configured, allowing clients to discover supported authentication assurance levels. Integration uses the IAcrMetadataProvider to retrieve configured values. Changes: - Add AcrValuesSupported property to ConfigurationResponse models - Update ConfigurationHandler to populate ACR values from provider - Update ConfigurationResponseFormatter to serialize ACR values to JSON * refactor: remove non-standard AMR values and document RFC 8176 compliance Remove non-standard Authentication Method Reference (AMR) values that are not present in the IANA registry or RFC 8176 specification. Comment out "bio", "oob", and "x509" constants with detailed explanations of why they are non-compliant and what standard alternatives should be used instead. The "oob" (out-of-band) identifier is used in OAuth for deprecated redirect URIs, not as an AMR value. RFC 8176 defines "sms" and "tel" for out-of-band methods. The generic "bio" should be replaced with specific biometric values like "face", "fpt", "iris", "retina", or "vbm". The "x509" should use "sc" (SmartCard) for certificate-based authentication per RFC 8176. This change improves standards compliance and provides clear migration guidance for developers using these values.
Fix dynamic client registration JWKS validation to properly handle credential validation.
…nto release/2.2
…ssue Fix GitHub Actions security vulnerability by validating user-controlled inputs before using them in action parameters. The 'pre_release' input is now normalized to a validated boolean output to prevent injection attacks. Clean up codebase by removing commented code in AuthenticationMethodReferences and extracting nested code blocks into separate methods in AutoPostFormatter and FrontChannelLogoutResult for better readability and maintainability.
- Add explicit AttributeUsage to HttpGetOrPostAttribute for clarity (S3993) - Change TODO to NOTE in AuthenticationSchemeAdapter for future enhancement (S1135) - Remove redundant parameter name from ArgumentNullException.ThrowIfNull to preserve caller info (S3236) - Suppress S6934 in controllers where action-level routes make class-level route redundant
Address various SonarQube issues to improve code quality and maintainability: - S1006: Add default parameter value in JsonSerializationBinder to match interface - S1104: Convert public field to property in AuthorizationValidationContext - S4136: Group InvalidRequest method overloads together in ErrorFactory - S1066: Merge nested conditionals in AggregationExtensions - S1118: Make LicenseLoader class static as all members are static - S4487: Suppress warning for timer field in LicenseLogger (must remain alive) - S7758: Use String.fromCodePoint in loop instead of apply() in checkSession.html - S127: Replace for loop with while loop in EnumerableExtensions to avoid updating counter in body
- Fix S125: Remove commented code from AuthenticationMethodReferences.cs - Fix S4138: Use for-of loop in checkSession.html for better code quality
- Fix race condition in IsAllowed using atomic AddOrUpdate operation - Improve cleanup loop efficiency by collecting keys before removal - Add null validation in Init method - Fix misleading documentation in Log method (doesn't implement throttling directly) - Document singleton lifetime and timer lifecycle in class remarks
- Add comprehensive XML documentation explaining timer callback purpose - Document that method prevents unbounded memory growth - Include parameter documentation with proper see-cref reference
- Rename method to better describe its purpose - More descriptive than generic OnTimer callback name
717b57f to
1e1eefe
Compare
- Include specific error details from JWT validation in error message - Convert error to lowercase for consistency with error message style - Apply changes to both IdTokenHintValidator and UserIdentityValidator - Helps developers debug token validation issues more effectively
- Create extension method for formatting JWT validation errors with proper capitalization - Support both standalone error messages (preserve caps) and embedded messages (lowercase first) - Apply to IdTokenHintValidator, UserIdentityValidator, and UserInfoRequestValidator - Provides consistent, user-friendly error messages across all JWT validation points - Includes comprehensive XML documentation with usage examples
- Fix incorrect false.ToDescription() to error.ToString() - Use default ToString() which returns error description with preserved capitalization
Modify ClientJwtValidator to accept either the token endpoint URL or the authorization server's issuer identifier as valid audience values in client assertion JWTs. This complies with RFC 7523 Section 3 and OpenID Connect Core 1.0 Section 9, which specify both values are acceptable. Changes: - Add IIssuerProvider dependency to access issuer identifier - Update ValidateAudience to check both requestUri and issuer - Enhance logging to show both expected audience values - Add test coverage for issuer identifier as audience
Update CodeQL Action to v4 to address deprecation warning. CodeQL Action v3 will be deprecated in December 2026. Changes: - Update github/codeql-action/init from v3 to v4 - Update github/codeql-action/analyze from v3 to v4
Add CanEncrypt, CanDecrypt, CanSign, and CanVerify properties to JsonWebKey base class and all derived types (RSA, EC, Octet). These properties determine key usability based on available key material: - RSA: public key (Modulus+Exponent) for encrypt/verify, private key (PrivateExponent) for decrypt/sign - EC: public key (X+Y+Curve) for encrypt/verify, private key (PrivateKey) for decrypt/sign - Octet: symmetric key (KeyValue) required for all operations Add runtime validation in JsonWebTokenSigner and JsonWebTokenEncryptor that checks key capabilities before performing cryptographic operations. Throws InvalidOperationException with descriptive messages when keys lack required material. Add comprehensive test suite covering all key types, edge cases, and consistency with Sanitize behavior.
cd42de0 to
8a96bfa
Compare
Add [JsonIgnore] attributes to computed capability properties in all JsonWebKey implementations (RSA, EC, Octet). These properties are derived from the presence of key material and should not be included when serializing keys to JSON format, as they would introduce non-standard fields into the JWK structure.
…gement Add Path property to CheckSessionCookieOptions to allow restricting session cookie scope to the check_session_iframe endpoint. Also improve cache prevention headers with comprehensive directives (no-store, no-cache, must-revalidate, max-age=0, Expires) for maximum browser compatibility. This removes the custom HttpResponseHeaders class in favor of standard Microsoft.Net.Http.Headers constants.
Fixes SonarCloud S107 (constructor has 8 parameters, max 7 authorized). Changes: - Remove ILogger and IServiceProvider from constructor (8 → 6 params) - Remove runtime validation in favor of XML documentation - Document session cookie requirements in SessionManagementService - Update CheckSessionCookieOptions docs to clarify SameSite must be "None"
c0ac7ca to
10e0988
Compare
Updates: - Microsoft.Extensions.* packages: 10.0.1 → 10.0.2 - Microsoft.SourceLink.GitHub: 8.0.0 → 10.0.102 - Grpc.AspNetCore: 2.71.0 → 2.76.0 - Google.Protobuf: 3.33.2 → 3.33.5 - Microsoft.AspNetCore.Http.Abstractions: 2.3.0 → 2.3.9
The test was using shared options with Path defaulting to "/", but it should test the fallback behavior when Path is empty. Now creates isolated options with Path="" to properly test that empty path falls back to RequestInfoProvider.PathBase.
…pport Replace programmatic XML-based HTML generation with a template-based approach using an embedded HTML resource. The new FrontChannelLogoutService generates cryptographically secure CSP nonces per request, enabling Content-Security-Policy headers that protect against XSS attacks while allowing the inline script for iframe synchronization. The HTML template includes browser compatibility improvements: lang attribute, charset meta tag, and zero-iframes handling for edge cases.
Add Content-Security-Policy nonce support to check_session_iframe for XSS protection. Fix browser compatibility issues in checkSession.html: correct DOCTYPE declaration, add charset meta tag, replace ES2020+ features (replaceAll, nullish coalescing) with ES5-compatible alternatives for older browser support.
Extract SetNoCacheHeaders extension method for HttpResponse to eliminate duplication between ActionResult decorators and GeneratedHtmlResult. Use typed headers with CacheControlHeaderValue for type safety and add s-maxage directive for shared cache prevention.
Add sealed modifier to private CheckSessionHtmlResult class. Switch to String.replaceAll() for base64url encoding in checkSession.html.
…3, add RFC 8414 and RFC 8176
Update NuGet package dependencies: - Microsoft.Extensions.* 10.0.2 → 10.0.3 - Microsoft.SourceLink.GitHub 10.0.102 → 10.0.103 - coverlet.collector 6.0.4 → 8.0.0 - System.IdentityModel.Tokens.Jwt 8.15.0 → 8.16.0 Bump version to 2.2 in all publishable packages: - AssemblyVersion: 2.1.0 → 2.2.0 - FileVersion: 2.1.0 → 2.2.0 - PackageVersion: 2.1 → 2.2 Update PackageReleaseNotes to reference v2.2 release.
Replace the single generic Nuget/README.md with tailored READMEs for each package (Utils, DependencyInjection, JWT, OIDC.Server, OIDC.Server.MVC) highlighting package-specific features, v2.2 changes, and relevant standards.
Release notes live in signed tag annotations. Migration guide is in MIGRATION-2.0.md. Simplified RELEASE_NOTES gitignore pattern.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Release v2.2 - Custom JWT Implementation & OpenID Connect Enhancements
Custom JWT Implementation
Implemented complete JWT signing and encryption infrastructure optimized exclusively for JSON tokens, eliminating
Microsoft.IdentityModel.Tokensdependency from production code. Uses modernJsonObject-based programming model fromSystem.Text.Json.Nodesdesigned specifically for JWT workflows.Key improvements:
Enhanced JWE Algorithm Support
Added support for
RSA-OAEP-256(RSA-OAEP with SHA-256) and AES-GCM key wrapping algorithms (A128GCMKW,A192GCMKW,A256GCMKW) that were not available in Microsoft's JWT library.Benefits:
DirectKeyAgreement Algorithm
Implemented RFC 7518 Section 4.5 direct key agreement (
diralgorithm) for JWE where the Content Encryption Key (CEK) is the shared symmetric key itself.Use cases:
JsonWebKey Operation Capabilities
Added
CanEncrypt,CanDecrypt,CanSign, andCanVerifyproperties to all JsonWebKey types (RSA, EC, Octet) with runtime validation. Keys are checked for required material before performing cryptographic operations.ACR Values Support
Added
acr_values_supportedmetadata to OpenID Connect discovery document per OpenID Connect Discovery 1.0. IntroducedIAcrMetadataProviderinterface for configurable Authentication Context Class Reference values.RFC 8176 AMR Compliance
Removed non-standard Authentication Method Reference values not present in IANA registry. Documented proper RFC 8176 alternatives for migration guidance.
Interoperability Validation
Added comprehensive interoperability tests verifying bidirectional compatibility between Abblix JWT implementation and
Microsoft.IdentityModel.TokensJsonWebTokenHandler.Coverage:
Bug Fixes
ObjectDisposedExceptionwhen HttpClient disposes shared singleton handlerInvalidOperationExceptionwhen serializingJsonValue<string>instances during session sign-inPathproperty toCheckSessionCookieOptionsfor restricting session cookie scopeexp/nbfclaims for OIDC request objects; support client identification viaclient_idclaim when issuer is missingCode Quality & Refactoring
ToDescriptionextension methodLicenseLoggerthread safety with atomic operationsAuthorizationResponseFormatterconstructor parametersSecurity & Maintenance