oscerd opened a new pull request, #1910:
URL: https://github.com/apache/camel-spring-boot/pull/1910
`UndertowSpringSecurityCustomizer.jwtDecoderByIssuerUri()` built the decoder
from the JWK set URI and
installed only a claim-set converter:
```java
final NimbusJwtDecoder jwtDecoder =
NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build();
jwtDecoder.setClaimSetConverter(new
KeycloakUsernameSubClaimAdapter(getProvider().getUserNameAttribute()));
return jwtDecoder;
```
Despite the bean name, no `setJwtValidator` call was made, so the default
validator applied: signature and
timestamps were checked, the `iss` claim was not, and the configured
`clientId` was used only to build the
`ClientRegistration` — never bound to the token. Spring Security's own
`withIssuerLocation` path installs an
issuer validator; this construction path does not.
**Why the audience check is the substantive part.** Pinning the JWKS URI
already ties tokens to the realm, so
issuer validation alone adds little — every client of that realm shares the
same signing key. A token minted
for a different client of the same realm therefore validated here. Binding
the token to the configured client
is what closes that.
### Change
```java
final OAuth2TokenValidator<Jwt> withIssuer =
JwtValidators.createDefaultWithIssuer(issuerUri);
if (!getProvider().isValidateAudience()) {
return withIssuer;
}
return new DelegatingOAuth2TokenValidator<>(withIssuer,
new JwtAudienceValidator(getClientRegistration().getClientId()));
```
`JwtAudienceValidator` accepts a token whose `aud` contains the configured
client id, or — for providers such
as Keycloak that record the requesting client separately — whose `azp`
equals it.
The issuer is derived from the same `url` + `realmId` the client
registration already resolves, via a shared
`realmUri()` helper, so the issuer is by construction the prefix of the JWK
set URI (asserted in a test).
### Behaviour change and opt-out
This is deliberate: a deployment presenting tokens minted for a *different*
client will now be rejected, which
is the point. For anyone relying on that:
```properties
camel.security.undertow.keycloak.validate-audience = false
```
Documented in `intro.adoc`, and it surfaces in config metadata. Worth an
upgrade-guide entry in `apache/camel`
when this lands — happy to open that.
### Tests
This starter had **no test module**; this adds one along with
`spring-boot-starter-test` (test scope only,
outside the generated dependency block).
- `JwtAudienceValidatorTest` — 5 cases: accepted via `aud`, accepted via
`azp`, accepted when one of several
audiences, **rejected for another client of the same realm**, rejected
when neither claim is present.
- `KeycloakIssuerUriTest` — 4 cases: issuer derivation, path on the
configured URL ignored, issuer is the
prefix of the generated JWK set URI (guards the two from drifting apart),
and audience validation defaults on.
9 tests, all passing. Full reactor `mvn clean install -DskipTests` — BUILD
SUCCESS.
### Not addressed here
CAMEL-24497 also notes that the registration of the non-static inner
`@EnableWebSecurity SecurityConfiguration`
is statically unconfirmed, and suggests a test asserting the filter chain
actually installs. I have **not**
added that — it needs a Spring context with a reachable provider, which is a
different kind of test than the
unit coverage above. Left on the issue; if the chain never registers, that
is a separate and worse fail-open
than this one.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]