IdTokenClaimsValidator skips aud
claim validation if token is issued by same identity issuer/provider.
See https://github.com/micronaut-projects/micronaut-security/blob/master/security-oauth2/src/main/java/io/micronaut/security/oauth2/client/IdTokenClaimsValidator.java#L202
This logic violates point 3 of https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation.
Workaround exists by setting micronaut.security.token.jwt.claims-validators.audience
with valid values.
micronaut.security.token.jwt.claims-validators.openid-idtoken
can be kept as default on.
Should probably be:
return issuer.equalsIgnoreCase(iss) &&
audiences.contains(clientId) &&
validateAzp(claims, clientId, audiences);
Any OIDC setup using Micronaut where multiple OIDC applications exists for the same issuer but token auth are not meant to be shared.
Please upgrade to a patched micronaut-security-oauth2
release as soon as possible.
If you cannot upgrade, for example, if you are still using Micronaut Framework 2, you can patch your application by creating a replacement of IdTokenClaimsValidatorReplacement
```java package cve;
import io.micronaut.context.annotation.Replaces; import io.micronaut.context.annotation.Requires; import io.micronaut.core.annotation.NonNull; import io.micronaut.core.util.StringUtils; import io.micronaut.security.config.SecurityConfigurationProperties; import io.micronaut.security.oauth2.client.IdTokenClaimsValidator; import io.micronaut.security.oauth2.configuration.OauthClientConfiguration; import io.micronaut.security.oauth2.configuration.OpenIdClientConfiguration; import io.micronaut.security.token.jwt.generator.claims.JwtClaims; import io.micronaut.security.token.jwt.validator.JwtClaimsValidatorConfigurationProperties;
import javax.inject.Singleton; import java.net.URL; import java.util.Collection; import java.util.List; import java.util.Optional;
@Requires(property = SecurityConfigurationProperties.PREFIX + ".authentication", value = "idtoken") @Requires(property = JwtClaimsValidatorConfigurationProperties.PREFIX + ".openid-idtoken", notEquals = StringUtils.FALSE) @Singleton @Replaces(IdTokenClaimsValidator.class) public class IdTokenClaimsValidatorReplacement extends IdTokenClaimsValidator { public IdTokenClaimsValidatorReplacement(Collection<OauthClientConfiguration> oauthClientConfigurations) { super(oauthClientConfigurations); }
@Override
protected boolean validateIssuerAudienceAndAzp(@NonNull JwtClaims claims,
@NonNull String iss,
@NonNull List<String> audiences,
@NonNull String clientId,
@NonNull OpenIdClientConfiguration openIdClientConfiguration) {
if (openIdClientConfiguration.getIssuer().isPresent()) {
Optional<URL> issuerOptional = openIdClientConfiguration.getIssuer();
if (issuerOptional.isPresent()) {
String issuer = issuerOptional.get().toString();
return issuer.equalsIgnoreCase(iss) &&
audiences.contains(clientId) &&
validateAzp(claims, clientId, audiences);
}
}
return false;
}
} ``
{ "nvd_published_at": "2023-10-09T14:15:10Z", "cwe_ids": [ "CWE-284" ], "severity": "MODERATE", "github_reviewed": true, "github_reviewed_at": "2023-10-05T20:55:14Z" }