Repository navigation
Replies: 1 comment
|
As a first proof-of-concept, this is a working (AI-assisted) reference branch -- feature/50043_protected_header_params. I'd like to agree on the direction here first, before moving on to issues/PRs. It's structured as two self-contained parts, so they can become separate PRs if you prefer (regarding question 4 above):
Existing crypto tests pass unchanged, and I added coverage for the new paths. The security constraints listed above are met. Ready to rework, re-split, or drop any part per your guidance, and to turn it into issue(s)/PR(s) once the direction looks right. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
I would like to discuss an extension to Keycloak's JOSE model before opening an enhancement issue and a PR.
Context
Keycloak already has pluggable JWE key management (
alg) and content encryption (enc) throughCekManagementProviderFactoryandContentEncryptionProviderFactory. Since #23928,JWEAlgorithmProvideralso receives theJWEHeaderwhen decoding and theJWEHeaderBuilderwhen encoding. So most of the plumbing is already there.The missing part is the protected header:
JWEHeaderhas a fixed set of fields, and unknown fields are ignored.This blocks external providers that need one more protected header parameter. On encode, the provider cannot write that parameter. On decode, Keycloak drops it before the provider sees the header.
The
epkfield maps toECPublicJWK, which is a plainkty/crv/x/yholder, so it can already carry any EC JWK, not just the NIST P-curves. It is insufficient only for a genuinely non-EC ephemeral key (such as a PQC KEM encapsulation).There is no
critsupport either, on the JWE or the JWS side. On the JWS side, however,JWSHeaderalready retains unknown parameters through a catch-all (@JsonAnyGetter/@JsonAnySetter otherClaims), so its only gap iscritenforcement.Motivation
This matters for:
CekManagementProviderFactorySPI that need one extra protected header parameter beyond the standard JOSE set. The ephemeral key itself can be a standard EC JWK that fits the existing epk/ECPublicJWK field unchanged; only the additional parameter has nowhere to go today.Proposal
This proposal is to let external providers express their required header data safely (not proposing to add algorithms to Keycloak core).
critto the JOSE header model.On encode, a provider can mark the extra protected parameters that are critical.
On decode, Keycloak rejects a token if
critlists a parameter that is not declared understood by the recipients active algorithm provider -- for JWE, the CEK-management provider's owned parameter allow-list; for JWS, the caller's declared understood set -- or that is absent from the protected header. This follows RFC 7515 section 4.1.11 (and RFC 7516 section 4.1.13 for JWE), and avoids silently accepting unknown protected data.This should not be a free-form JSON bag. A provider should declare the extra parameters it owns. Keycloak should serialize and parse only those parameters, and should validate them against that provider's allow-list.
In this proposal the declaration hook is on the
algside (CekManagementProviderFactory); content-encryptionencproviders are out of scope here, and an analogous hook on ContentEncryptionProviderFactory can be added separately if anencalgorithm ever needs its own protected parameters.I would avoid
@JsonAnyGetterand@JsonAnySetter. They are easy to add, but they make it too easy to accept attacker-controlled header fields by accident.epkhandling as it is for EC algorithms.ECPublicJWK already carries any EC JWK; the strictness that matters for ECDH-ES is applied when the key is consumed (point/curve checks), and must stay. EC-based algorithms use the existing
epkfield as-is, no change needed. A separate provider-owned ephemeral-key representation is only relevant for genuinely non-EC keys (e.g. a PQC KEM encapsulation) and can be tracked separately.For JWE, the protected header is also the AAD for the authentication tag. On decode, Keycloak must continue to use the received base64url header bytes, not a re-serialized header. Extra parameters should be parsed for provider use without changing the bytes used for tag verification. On encode, serialization should be deterministic.
This should not require a
JWEAlgorithmProviderAPI change, because the provider already receives the header or builder.I can implement the core change, tests, and documentation. Any AI-assisted development will be disclosed as required.
Constraints
requestObjectSignatureAlgand the configured encryption constraints.Questions
critbe part of this change, or should it be tracked first as a separate JOSE feature?Related
I did not find an existing issue or discussion for generic provider-owned JWE protected header parameters or for
critsupport in Keycloak's JOSE code.All reactions