Related to https://github.com/spring-projects/spring-security/issues/10117#issuecomment-883638049
ClaimAccessor#getClaimAsBoolean currently coerces any type into a Boolean, which is somewhat surprising when it is a map or list.
For example, the following snippet will somewhat surprisingly pass:
ClaimAccessor claims = () -> Collections.singletonMap("claim", new HashMap<>());
assertThat(claims.getClaimAsBoolean("claim")).isFalse();
In reality, the above is a usage error. It would be better for the application to complain so that the developer can adjust their system.
getClaimAsBoolean should match core Java behavior more closely. It should only coerce booleans and Strings (like "true" and "FALSE") into Booleans.
The logic to change is in ObjectToBooleanConverter where it does:
return Boolean.valueOf(source.toString());
This should instead do something like the following:
if (source instanceof String) {
return Boolean.valueOf((String) source);
}
return null;
Then, getClaimAsBoolean should introduce an assertion, similar to the assertions in the other getClaimAsXXX methods:
Object claimValue = getClaims().get(claim);
Boolean convertedValue = ClaimConversionService.getSharedInstance().convert(claimValue, Boolean.class);
Assert.isNotNull(convertedValue, () -> "Unable to convert claim '" + claim + "' of type '" + claimValue.getClass() + "' to Boolean.");
return convertedValue;
Thereafter, if an application really needs the old behavior, it can register a custom converter like so:
ClaimConversionService.getInstance().addConverter(new MyObjectToFalsyBooleanConverter());
during application startup.
Comment From: ahmedmq
@jzheaux - Could I work on this issue please?
Comment From: sjohnr
It's yours, @ahmedmq!
Comment From: qavid
@jzheaux, @sjohnr I have created PR #10356. Please take look.