2

Hoping someone can help me on this. I've created my own Keycloak Realm, and client. I am using Spring boot and KeycloakRestTemplate from org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate; to make all my calls.

I've been successful in adding client-level roles to the user role mapping to any given user.

I prefix my URI with /admin/realms/ when using the Keycloak API docs. So far all my requests have worked (getting a list of users from my client, getting a list of users that have a particular client-level role, and even adding client-level roles to a user as described above)

My problem is I cannot delete client-level roles from a user. I've looked at the keycloak docs and it looks like I've followed everything correctly. I also made sure the user had applicable client roles available to be deleted. I really appreciate any comments or help given!!

https://www.keycloak.org/docs-api/14.0/rest-api/index.html

"Delete client-level roles from user role mapping DELETE /{realm}/users/{id}/role-mappings/clients/{client}"

import org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate;

.
.
.


    @Autowired
        private KeycloakRestTemplate restTemplate;
.
.
.
.
.


UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(keycloakServerUrl + "/admin/realms/"+keycloakRealm+"/users/"+userId+"/role-mappings/clients/"+keycloakClientId);

this.restTemplate.postForEntity(builder.toUriString(), rolesList, List.class);  // this works! Note: rolesList is an List<RoleRepresentation> object

.
.
.

this.restTemplate.delete(builder.toUriString(), rolesList); // Does not work!

URI: http://XXXXXXXXXXXXXXX:8180/auth/admin/realms/VLS/users/2144cc43-59f4-4406-9527-2a59ee0c3751/role-mappings/clients/53e659e1-7cef-4dbb-8cdd-b786ca3a44a4

Error when calling Delete API: org.springframework.web.client.HttpClientErrorException$UnsupportedMediaType: 415 Unsupported Media Type: [{"error":"RESTEASY003065: Cannot consume content type"}]

Edit 1: I have also given myself ALL available roles from all clients as a precaution beforehand. I understand some roles are needed to perform certain tasks even through the API. I've taken this into account.

Ali_Ahmed
  • 23
  • 3
  • Just as a quick idea, have you thought about setting the application/json value as content type? – botscripter Jun 22 '21 at 23:01
  • Thank you for your response! @rimesc resolved my problem below. According to the KeycloakRestTemplate class all of it's methods are inherited from Spring's RestTemplate and "The main advantage to using this class over Spring's RestTemplate is that authentication is handled automatically when both the service making the API call and the service being called are protected by Keycloak authentication." so i believe this class automatically appends the application/json header with every request. – Ali_Ahmed Jun 24 '21 at 16:21

2 Answers2

0

KeycloakRestTemplate appears to inherit all of its methods directly from Spring’s RestTemplate. According to the documentation for that class, the second argument to delete isn’t a request body, as I think you’re intending. Rather, it’s a vararg of objects used to expand template variables in the URI.

There doesn’t appear to be a variant of the delete method that allows you to supply a body, so you’ll probably need to use one of the variants of the execute or exchange methods that accepts an HTTP method and a request entity instead. In fact, the RestTemplate API makes this quite difficult to do, because it’s generally assumed that DELETE requests don’t have bodies.

rimesc
  • 158
  • 2
  • 7
  • Thank you so much!! You hit the nail on the head :) I went with your advice and used the exchange method since I had a request body for my delete request and it went through successfully! `HttpEntity> request = new HttpEntity>(deleteRolesList); this.restTemplate.exchange(builder.toUriString(), HttpMethod.DELETE, request, List.class); ` – Ali_Ahmed Jun 24 '21 at 16:13
0

The alternate way to interact with Keycloak can be using the keycloak starter dependency and the keycloak admin client.

  1. Add the dependencies mentioned above.

  2. Configure the Keycloak admin user.

    public Keycloak getAdminKeycloakUser() {
    return KeycloakBuilder.builder()
        .serverUrl(keycloakAuthUrl)
        .grantType(OAuth2Constants.PASSWORD)
        .realm(masterRealm).clientId(masterClient)
        .username(adminUsername).password(adminPassword)
        .resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build())
        .build();
    }
    

With this admin user we can delete the client user along with other actions.

getAdminKeycloakUser().realm(realm).clients().roles().deleteRole(roleName);
Akhilesh Magdum
  • 324
  • 2
  • 13