Handle Null Group Attributes in /participants Endpoint to Prevent 500 Error
Bug in Release/1.3.0
There is an issue in the /participants endpoint that caused a 500 Internal Server Error when the endpoint attempted to process groups in Keycloak that lack required attributes
When making a GET request to /participants, the endpoint fetches all groups in Keycloak. If any group is missing required attributes (e.g., ATR_NAME, ATR_PUBLIC_KEY, or ATR_SD_HASH), a NullPointerException occurs in toParticipantExt, causing a server error. This can occur if groups are created directly in Keycloak and do not meet the expected structure.
Quick fix: on ParticipantDaoImpl file
- Update the toParticipantExt method to safely handle missing attributes and returning null if a group is missing required fields.
private ParticipantMetaData toParticipantExt(GroupRepresentation groupRepo) {
Map<String, List<String>> attributes = groupRepo.getAttributes();
// Check for required attributes and log if any are missing
if (attributes.get(ATR_NAME) == null || attributes.get(ATR_NAME).isEmpty() ||
attributes.get(ATR_PUBLIC_KEY) == null || attributes.get(ATR_PUBLIC_KEY).isEmpty() ||
attributes.get(ATR_SD_HASH) == null || attributes.get(ATR_SD_HASH).isEmpty()) {
return null;
}
return new ParticipantMetaData(groupRepo.getName(), attributes.get(ATR_NAME).get(0),
attributes.get(ATR_PUBLIC_KEY).get(0), null, attributes.get(ATR_SD_HASH).get(0));
}
- Update the search method to filter out null results (representing incomplete or unknown groups), ensuring only valid ParticipantMetaData instances are counted and returned.
public PaginatedResults<ParticipantMetaData> search(Integer offset, Integer limit) {
GroupsResource instance = keycloak.realm(realm).groups();
List<GroupRepresentation> groups = instance.groups(null, offset, limit, false);
// Map groups to ParticipantMetaData, filter non-null values, and collect
List<ParticipantMetaData> validParticipants = groups.stream()
.map(this::toParticipantExt)
.filter(Objects::nonNull)
.collect(Collectors.toList());
// Set total as the count of valid ParticipantMetaData instances
long total = validParticipants.size();
return new PaginatedResults<>(total, validParticipants);
}