Skip to content

Antalya 26.1: Add support for EC JWT validation #1596

Merged
zvonand merged 2 commits intoantalya-26.1from
fix/antalya-26.1/oauth-30032026
Apr 1, 2026
Merged

Antalya 26.1: Add support for EC JWT validation #1596
zvonand merged 2 commits intoantalya-26.1from
fix/antalya-26.1/oauth-30032026

Conversation

@zvonand
Copy link
Copy Markdown
Collaborator

@zvonand zvonand commented Mar 30, 2026

Changelog category (leave one):

  • Improvement

Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):

Add support for EC JWT validation (ES* algorithms)

CI/CD Options

Exclude tests:

  • Fast test
  • Integration Tests
  • Stateless tests
  • Stateful tests
  • Performance tests
  • All with ASAN
  • All with TSAN
  • All with MSAN
  • All with UBSAN
  • All with Coverage
  • All with Aarch64
  • All Regression
  • Disable CI Cache

Regression jobs to run:

  • Fast suites (mostly <1h)
  • Aggregate Functions (2h)
  • Alter (1.5h)
  • Benchmark (30m)
  • ClickHouse Keeper (1h)
  • Iceberg (2h)
  • LDAP (1h)
  • Parquet (1.5h)
  • RBAC (1.5h)
  • SSL Server (1h)
  • S3 (2h)
  • S3 Export (2h)
  • Swarms (30m)
  • Tiered Storage (2h)

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 30, 2026

Workflow [PR], commit [8b65380]

@zvonand zvonand changed the title add EC support Antalya-26.1: Add support for EC JWT validation Mar 30, 2026
@zvonand zvonand added the port-antalya PRs to be ported to all new Antalya releases label Mar 30, 2026
@zvonand
Copy link
Copy Markdown
Collaborator Author

zvonand commented Mar 30, 2026

I will add a verified label -- the PR is small and has a test. It cannot be verified any further. As soon as the tests are fine -- I will merge it

@zvonand zvonand added the verified Approved for release label Mar 30, 2026
@zvonand zvonand changed the title Antalya-26.1: Add support for EC JWT validation Antalya 26.1: Add support for EC JWT validation Mar 30, 2026
@mkmkme
Copy link
Copy Markdown
Collaborator

mkmkme commented Mar 31, 2026

AI audit note: This review comment was generated by AI (claude-4.6-opus).

Audit update for PR #1596 (Add support for EC JWT validation — ES* algorithms):

Confirmed defects

  1. Medium: EC_KEY resource leak on EVP_PKEY_assign_EC_KEY failure

    • Impact: Memory leak of the EC_KEY object if the assignment to EVP_PKEY fails (e.g., under OOM).
    • Anchor: src/Access/TokenProcessorsJWT.cpp / create_public_key_from_ec_components
    • Trigger: EVP_PKEY_assign_EC_KEY returns failure after ec_key.release() has already relinquished ownership from the unique_ptr.
    • Why defect: ec_key.release() is called as the argument to EVP_PKEY_assign_EC_KEY. If the call fails, the raw EC_KEY* pointer is no longer owned by any RAII wrapper, so it leaks. This is a standard ownership-transfer-before-check anti-pattern.
    • Code evidence:
      if (EVP_PKEY_assign_EC_KEY(evp_key.get(), ec_key.release()) != 1)
          throw Exception(ErrorCodes::AUTHENTICATION_FAILED, "JWT cannot be validated: failed to assign EC key");
    • Fix direction: Save the raw pointer before release, call EVP_PKEY_assign_EC_KEY on it, and only release from unique_ptr on success; or manually EC_KEY_free on failure.
    • Regression test direction: Difficult to unit-test (requires OOM injection); code review fix is sufficient.
  2. Medium: Use of OpenSSL 3.0-deprecated EC_KEY APIs with OpenSSL 3.5.5

    • Impact: Build deprecation warnings; potential breakage when deprecated APIs are removed in a future OpenSSL release. Bypasses OpenSSL 3.x provider-level checks.
    • Anchor: src/Access/TokenProcessorsJWT.cpp / create_public_key_from_ec_components
    • Trigger: Compiling against OpenSSL >= 3.0 (ClickHouse currently uses 3.5.5).
    • Why defect: EC_KEY_new_by_curve_name, EC_KEY_free, EC_KEY_set_public_key, EC_KEY_get0_group, EVP_PKEY_assign_EC_KEY are all marked OSSL_DEPRECATEDIN_3_0. The jwt-cpp library itself uses #ifdef JWT_OPENSSL_3_0 guards to use the modern OSSL_PARAM_BLD + EVP_PKEY_fromdata API for its RSA key construction. This new EC function should follow the same pattern.
    • Fix direction: Use OSSL_PARAM_BLD + EVP_PKEY_fromdata with EVP_PKEY_EC for OpenSSL 3.0+, guarded by #ifdef JWT_OPENSSL_3_0 or OPENSSL_VERSION_NUMBER >= 0x30000000L.
    • Regression test direction: Verify EC JWT validation works after switching to the modern API path.
  3. Low: Key-type dispatch by claim presence rather than kty field

    • Impact: A JWK that contains both x/y and n/e claims (malformed or adversarial) will always be routed to the EC path, even for RS* algorithms. Result is fail-closed (throws "unknown algorithm"), but the error message is misleading.
    • Anchor: src/Access/TokenProcessorsJWT.cpp / JwksJwtProcessor::resolveAndValidate, the if (jwk.has_jwk_claim("x") && jwk.has_jwk_claim("y")) block.
    • Trigger: A JWKS server returns a JWK with both EC and RSA parameters; the JWT uses an RS* algorithm.
    • Why defect: RFC 7517 requires kty to determine key type. Checking kty == "EC" before entering the EC path (and kty == "RSA" before RSA) would prevent misrouting. The pre-existing RSA-only code didn't need this since it was the only path, but with two key types the dispatch needs disambiguation.
    • Fix direction: Check jwk.get_key_type() == "EC" (or the raw kty claim) before entering the EC branch, and kty == "RSA" before the RSA branch.
    • Regression test direction: Add a test with a JWK containing both EC and RSA claims, verify correct routing.

Coverage summary

  • Scope reviewed: All 4 changed files — TokenProcessorsJWT.cpp (new create_public_key_from_ec_components function, EC dispatch in JwksJwtProcessor::resolveAndValidate, algorithm registration), tokens.md (doc), server.py (test JWKS), test.py (integration test).
  • Categories failed: Resource lifetime (EC_KEY leak on error), API deprecation/portability (OpenSSL 3.0), Key-type disambiguation.
  • Categories passed: Base64url decoding correctness, curve NID mapping (ES256→P-256, ES384→P-384, ES512→P-521), crv claim cross-validation when present, algorithm-verifier registration for ES256/ES384/ES512, BIO lifetime safety, PEM serialization correctness, error-path fail-closed behavior, integration test coverage for ES384.
  • Assumptions/limits: Pre-existing data race on mutable verifier in JwksJwtProcessor::resolveAndValidate (concurrent threads writing without synchronization) is out-of-scope for this PR but is a known risk; pre-existing es256k omission from JWKS path also out-of-scope.

@zvonand zvonand merged commit d50866c into antalya-26.1 Apr 1, 2026
330 of 340 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

antalya antalya-26.1 antalya-26.1.6.20001 port-antalya PRs to be ported to all new Antalya releases verified Approved for release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants