Create a scope and assign it to a client using the keycloak admin Java SDK

I’m using the keycloak admin Java library to create a scope in my realm, like so:

ClientScopeRepresentation openidScope = new ClientScopeRepresentation();
openidScope.setName("openid");
openidScope.setProtocol("openid-connect");
scopeResource.create(openidScope);

I’m then creating a Client that uses that scope:

ClientRepresentation clientRepresentation...
clientRepresentation.setDefaultClientScopes(List.of("openid", ...));
realm.clients().create(clientRepresentation);

I can see the scope listed in the Admin Console UI under the Client Scopes section:

But when I go to the Client itself and look under the Scopes tab, it’s not there.

So two questions:

  1. Notice that the Assigned type is None - I want this to be Default, but I can’t see a property to set on the ClientScopeRepresentation to make that happen, how do I do that?
  2. How do I assign this Client Scope to the Client?

Looking at the Network inspector when using the admin UI, when I assign a default scope I see a single request at the point of assignment that references the scope by its ID.

So I changed my code to find ClientScopeRepresentations by their names and set the default scopes to their IDs, but the association between the Client and the Client Scope still doesn’t happen.

Finally worked it out:

realm.clientScopes().findAll().stream()
    .filter(scope -> ALL_SCOPES.contains(scope.getName()))
    .forEach(clientScopeRepresentation -> clientResource.addDefaultClientScope(clientScopeRepresentation.getId()));

Hello Nathan,

Could you please tell me which type is the variable “scopeResource” and “clientResource” in your sample code?

I am trying to use your code to create a scope through java but so far no success. Could you possibly post here a more complete sample of your code?

Thank you for your time and attention!

Sure!

Here’s the full method:

    void setClientScopes(RealmResource realm) {
        ClientRepresentation clientRepresentation = getClientRepresentation(realm);
        ClientResource clientResource = getClientResource(realm, clientRepresentation);
        realm.clientScopes().findAll().stream()
            .filter(scope -> Scopes.names().contains(scope.getName()))
            .forEach(clientScopeRepresentation -> {
                log.info("Adding client scope: '{}' ({}) to client", clientScopeRepresentation.getName(), clientScopeRepresentation.getId());
                clientResource.addDefaultClientScope(clientScopeRepresentation.getId());
            });
    }

Hope it helps! If you need anything else, let me know.

Thank you very much Nathan!

I will give it a try as soon as i can and report back.

Since i only needed to add scopes to the realm and not to a client i ended up going with the code below for now:

public static void createScope(KeycloakSession session, String scopeName) {

    var realm = session.getContext().getRealm();

    var scopes = realm.getClientScopesStream()
        .filter(scope -> scope.getName().equals(scopeName))
        .toArray();

    if(scopes.length==0) {
        LOGGER.debug("creating client scope: scope={} to realm={}", scopeName, realm.getName());
        var newScope = realm.addClientScope(scopeName);
        newScope.setProtocol("openid-connect");
    }
}

Thanks again for the help Nathan!