Search code examples
keycloakkeycloak-serviceskeycloak-rest-api

How to add dedicated scope to Keycloak via kcadm


I'd like to add dedicated scopes to a client so that it can access information from other clients. Turning full access on works but grants too many permissions.

The scopes are already created with their respective clients. It is “only” a matter of assigning scope from client a to client b. I have a list of names and client ids available locally. How can I efficiently assign them via kcadm.sh?

I already tried with the network tab open but I couldn't wrap my head around what the logic behind assigning scopes is.

E.g., there is a

  • POST /admin/realms/master/clients/968c7b36-95dd-4121-b92b-37b324298890/scope-mappings/realm with an empty array as payload
  • POST /admin/realms/master/clients/968c7b36-95dd-4121-b92b-37b324298890/scope-mappings/clients/74cb7b05-34d5-4657-8fe6-bb19a7c8a07f from the APIDOC it just says client. But I don't know what that client should be.

How to reproduce on Keycloak (X) 20.0.3

  1. Login to the Keycloak Admin Console
  2. Click on the client tab
  3. Click createClient
  4. Create client id and click next.
  5. Click save.
  6. On the new client. Click on the upper tab 'Client scopes'.
  7. Click on the first blue item.
  8. Click on the upper tab 'scope' and turn off full scope allowed.
  9. Click assign role and add one of the items.

This is what I want to achieve with the help of the kcadm.sh as clients are added dynamically. You can't even export the client from Actions->Export and Import it again from the UI. Every scope is lost when imported again.


Solution

  • To assign role from client A to client B at the bear minimal you need the following Rest Full API call:

    • POST /admin/realms/ <REALM NAME> /clients/< ID OF THE CLIENT >/scope-mappings/clients/< ID OF THE CLIENT where the role comes from>

    so in your case /admin/realms/ <REALM NAME> /clients/< ID OF CLIENT B >/scope-mappings/clients/ < ID OF CLIENT A>

    the payload should be [{"id":"<ID OF ROLE>","name":"<ROLE NAME>"}]

    You will need the call to get the id of the client for that you can call:

    GET /{realm}/clients
    

    with clientId as query parameter.

    And then you will need the call to get the ID of the role, for that you can use:

    GET /{realm}/clients/{id}/roles/{role-name}
    

    id is the id of the client.