{
  "parent_root_cause": "HardcodedPublicKeyLoader HMAC branch: when an Identity Provider is configured with useJwksUrl=false and publicKeySignatureVerifier set to the base64 content of an RSA public key (no PEM headers), and a JWT header specifies a symmetric algorithm (HS256/HS384/HS512), Base64Url.decode(encodedKey) yields the RSA public key DER (SubjectPublicKeyInfo) bytes, which are loaded as an HMAC SecretKey. Since the RSA public key is inherently public, an attacker can sign an HS256 JWT with those bytes and the signature verifies, bypassing JWT signature verification. Compounded by AbstractBaseJWTValidator.validateSignatureAlgorithm not rejecting symmetric algorithms (or 'none') when no expected algorithm is configured.",
  "parent_sink": "HardcodedPublicKeyLoader (HMAC branch) -> MacSignatureVerifierContext.verify() ; reached via PublicKeyStorageManager.getIdentityProviderKeyWrapper",
  "variant_root_cause": "Identical: the same HardcodedPublicKeyLoader HMAC branch is reached for the same hardcoded-base64-RSA-public-key IdP config when the attacker-controlled JWT header specifies HS256. The HMAC secret equals the RSA public key DER bytes; the forged HS256 signature verifies.",
  "variant_sink": "Same HardcodedPublicKeyLoader HMAC branch -> MacSignatureVerifierContext.verify(), reached via OIDCIdentityProvider.verifySignature() -> PublicKeyStorageManager.getIdentityProviderKeyWrapper() (instead of JWTAuthorizationGrantIdentityProvider.verifySignature() in the parent).",
  "shared_sink": true,
  "shared_root_cause": true,
  "same_key_loader": "HardcodedPublicKeyLoader",
  "same_crypto_primitive": "HS256 (HMAC-SHA256) with RSA public key DER bytes as the HMAC secret (algorithm confusion)",
  "difference": "Entry point / code path. Parent: JWT Authorization Grant (grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer + assertion) -> DefaultJWTAuthorizationGrantValidator (extends AbstractBaseJWTValidator) which calls validateSignatureAlgorithm (fix Layer 1) BEFORE verifySignature (Layer 2). Variant: OIDC external-internal token exchange (grant_type=urn:ietf:params:oauth:grant-type:token-exchange + subject_token) -> OIDCIdentityProvider.exchangeExternalImpl -> validateJwt -> verifySignature (Layer 2 ONLY; Layer 1 validateSignatureAlgorithm is NOT on this path).",
  "layer1_applies_to_parent": true,
  "layer1_applies_to_variant": false,
  "layer2_applies_to_parent": true,
  "layer2_applies_to_variant": true,
  "same_trust_boundary": true,
  "trust_boundary": "Unauthenticated/low-privilege network caller submits a forged JWT to the Keycloak OIDC token endpoint over HTTP; the JWT is verified against a hardcoded IdP public key.",
  "fix_closes_variant": true,
  "fix_closing_layer": "Layer 2 (HardcodedPublicKeyLoader HMAC-branch removal). Layer 1 does not run on the variant path, so the variant is closed only by Layer 2.",
  "confidence": "high"
}
