I created a custom Keycloak token mapper based on https://github.com/dasniko/keycloak-tokenmapper-example.
However, in my case, I wanted to add a list of values to the custom claim.
If I pass the list into mapClaim
, it only uses the first element of the list:
List<MyObject> myList = ...
OIDCAttributeMapperHelper.mapClaim(token, mappingModel, myList);
The solution is to add a static create
method in the custom AbstractOIDCProtocolMapper
subclass:
public class MyCustomTokenMapper extends AbstractOIDCProtocolMapper
implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
...
public static ProtocolMapperModel create(String name,
boolean accessToken,
boolean idToken,
boolean userInfo) {
ProtocolMapperModel mapper = new ProtocolMapperModel();
mapper.setName(name);
mapper.setProtocolMapper(PROVIDER_ID);
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
Map<String, String> config = new HashMap<>();
config.put(ProtocolMapperUtils.MULTIVALUED, Boolean.TRUE.toString()); // Set the MULTIVALUED config
if (accessToken) {
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
}
if (idToken) {
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
}
if (userInfo) {
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
}
mapper.setConfig(config);
return mapper;
}
}
This static method is called automatically by Keycloak when it is present (For clarity, the custom mapper also works without it, but you can't configure the MULTIVALUED and the claim would only show the first item from the list). It allows to set the MULTIVALUED attribute to true so we can return a list of things.