The only way I've found to solve this is to provide custom mapper as Keycloak extension.
So you can create a mapper which extends from the default AbstractOIDCProtocolMapper
and override the existing scope claim inside the transformAccessToken
method:
package com.example;
import org.keycloak.models.ClientSessionContext;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper;
import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.AccessToken;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CustomOIDCProtocolMapper extends AbstractOIDCProtocolMapper
implements OIDCAccessTokenMapper {
public static final String PROVIDER_ID = "oidc-custom-protocol-mapper";
@Override
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
token.getOtherClaims().put("scope", Arrays.asList(token.getScope().split(" ")));
setClaim(token, mappingModel, userSession, session, clientSessionCtx);
return token;
}
@Override
public String getDisplayCategory() {
return TOKEN_MAPPER_CATEGORY;
}
@Override
public String getDisplayType() {
return "Custom Scope Claim Mapper";
}
@Override
public String getHelpText() {
return "Modifies `scope` claim in resulting access token";
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return Collections.emptyList();
}
@Override
public String getId() {
return PROVIDER_ID;
}
}
Then register your mapper by creating the resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
text file:
com.example.CustomOIDCProtocolMapper
Then package the extension as a Jar file and put it into your Keycloak providers/
directory. If the extension is loaded properly, you should be able to add a mapper by going to your client settings.
Adding a mapper to a client
So your client Mappers tab content should look similar to this:
Resulting list of client mappers
Once the mapper is properly added to a client, the scope
claim is going to be mapped as JSON array in the resulting access token.
Documentation on Keycloak extension developent can be found here.