Initially, I couldn't create a client-level role using keycloak-admin-client. I decided to try to do this via the API using Postman in order to make sure that it doesn't work out that way either.
I think I'm sending the request correctly. The authorization token in the headers and the json representation of the role in the body. enter image description here enter image description here
I claim that the client exists, the user I use has administrator rights.
In my java project, it looks like this:
public int createClient(String clientId) {
ClientRepresentation clientRepresentation = new ClientRepresentation();
clientRepresentation.setClientId(clientId);
clientRepresentation.setPublicClient(false);
clientRepresentation.setEnabled(true);
clientRepresentation.setServiceAccountsEnabled(true);
Response response = clientsManager.create(clientRepresentation);
int statusCode = response.getStatus();
log.info("HTTP Status of client creation = {}", statusCode);
if (statusCode == 201) fillClientWithRoles(clientId);
return statusCode;
}
public void fillClientWithRoles(String clientId) {
ClientResource clientResource = clientsManager.get(clientId);
log.info("client: {}", clientResource);
for (ClientRole role : ClientRole.values()) {
RoleRepresentation roleRepresentation = new RoleRepresentation();
roleRepresentation.setName(role.name());
roleRepresentation.setClientRole(true);
roleRepresentation.setComposite(false);
clientResource.roles().create(roleRepresentation);
}
}
The Keycloak object is configured correctly. I can, for example, successfully create new users
I reread a bunch of articles, turned to bots for advice, but I still haven't found a solution that would explain the cause of the 404 error in this request and help solve the problem
2024-05-28T14:53:08.288+03:00 ERROR 14920 --- [portal-ms] [io-60005-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: jakarta.ws.rs.NotFoundException: HTTP 404 Not Found] with root cause
jakarta.ws.rs.NotFoundException: HTTP 404 Not Found
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.handleErrorStatus(ClientInvocation.java:242) ~[resteasy-client-6.2.9.Final.jar:6.2.9.Final]
at org.jboss.resteasy.client.jaxrs.internal.proxy.extractors.DefaultEntityExtractorFactory$3.extractEntity(DefaultEntityExtractorFactory.java:41) ~[resteasy-client-6.2.9.Final.jar:6.2.9.Final]
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:136) ~[resteasy-client-6.2.9.Final.jar:6.2.9.Final]
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:103) ~[resteasy-client-6.2.9.Final.jar:6.2.9.Final]
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:102) ~[resteasy-client-6.2.9.Final.jar:6.2.9.Final]
at jdk.proxy2/jdk.proxy2.$Proxy192.create(Unknown Source) ~[na:na]
at ru.gnivc.portalservice.service.KeycloakService.fillClientWithRoles(KeycloakService.java:124) ~[classes/:na]
at ru.gnivc.portalservice.service.KeycloakService.createClient(KeycloakService.java:109) ~[classes/:na]
at ru.gnivc.portalservice.service.CompanyService.createCompany(CompanyService.java:27) ~[classes/:na]
at ru.gnivc.portalservice.controller.CompanyController.createCompany(CompanyController.java:22) ~[classes/:na
The problem was that when contacting the client, we have to use the UUID assigned to him when creating (automatically). This is not at all obvious, because in the Keyclock UI it is not even displayed to customers. Below I will give an example of creating a client with assigning client roles to it.
I hope that it will help anyone who is faced with the same problem in the future!!!
//ClientsResource clientsManager = clientsManager = realm.clients(); - it is used further
public int createClient(String clientId) {
ClientRepresentation clientRepresentation = new ClientRepresentation();
clientRepresentation.setClientId(clientId);
clientRepresentation.setPublicClient(false);
clientRepresentation.setEnabled(true);
clientRepresentation.setServiceAccountsEnabled(true);
Response response = clientsManager.create(clientRepresentation);
int statusCode = response.getStatus();
if (statusCode == 201) {
String createdId = CreatedResponseUtil.getCreatedId(response); //here we can get client's assigned UUID
fillClientWithRoles(createdId);
}
return statusCode;
}
public void fillClientWithRoles(String clientId) {
ClientResource clientResource = clientsManager.get(clientId); //here we muse use UUID of the client
for (ClientRole role : ClientRole.values()) {
RoleRepresentation roleRepresentation = new RoleRepresentation();
roleRepresentation.setName(role.name());
roleRepresentation.setClientRole(true);
roleRepresentation.setComposite(false);
clientResource.roles().create(roleRepresentation);
}
}