Using the keycloak-admin-client
in Java, I've successfully created a new client and a new user. However, I can't seem to use the user to obtain a JWT for the client.
Here's my code:
// Create a keycloak instance with admin privs
Keycloak keycloak =
KeycloakBuilder.builder()
.serverUrl("http://localhost:8080/auth")
.grantType(OAuth2Constants.PASSWORD)
.realm("master")
.username("admin")
.password("adminPass")
.clientId("admin-cli")
.resteasyClient(new ResteasyClientBuilderImpl().connectionPoolSize(10).build())
.build();
// Edit: Create the realm "test-realm"
RealmRepresentation realmRep = new RealmRepresentation();
realmRep.setRealm("test-realm");
realmRep.setEnabled(true);
keycloak.realms().create(realmRep);
// Create the client "test-client"
ClientRepresentation clientRep = new ClientRepresentation();
clientRep.setClientId("test-client");
clientRep.setSecret(UUID.randomUUID().toString());
clientRep.setProtocol("openid-connect");
// ❌ Edit: This is the current problem, I need the client to be confidential.
clientRep.setBearerOnly(true);
// Edit: Added this but still getting 400
clientRep.setDirectAccessGrantsEnabled(true);
// Edit: Added this and it fixed part of the problem
clientRep.setEnabled(true);
keycloak.realm("test-realm").clients().create(clientRep);
// Create the user "test-user"
CredentialRepresentation credRep = new CredentialRepresentation();
credRep.setType(CredentialRepresentation.PASSWORD);
credRep.setValue("test-user-pass");
UserRepresentation userRep = new UserRepresentation();
userRep.setUsername("test-user");
userRep.setCredentials(Collections.singletonList(credRep));
// Edit: Added this and it fixed part of the problem
userRep.setEnabled(true);
keycloak.realm("test-realm").users().create(userRep);
// Create another Keycloak instance with the new user's credentials
keycloak =
KeycloakBuilder.builder()
.serverUrl("http://localhost:8080/auth")
.grantType(OAuth2Constants.PASSWORD)
.realm("test-realm")
.username("test-user")
.password("test-user-pass")
.clientId("test-client")
.clientSecret(clientRep.getSecret())
.resteasyClient(new ResteasyClientBuilderImpl().connectionPoolSize(10).build())
.build();
// Try and obtain a JWT
AccessTokenResponse atr = keycloak.tokenManager().getAccessToken(); // Fails with 400
DecodedJWT jwt = JWT.decode(atr.getToken());
This gives me a javax.ws.rs.BadRequestException: HTTP 400 Bad Request
but, unfortunately, I can't seem to get anything more helpful than that. I've debugged and can't discern any messages that would tell me what exactly is bad about my request.
I've also tried removing the client secret from creating the client and from passing it to the second Keycloak instance, but I still get the 400
.
Edit: I've tried looking at the logs (I'm running Keycloak in a Docker container) and nothing appears to be getting logged when this issue occurs.
Edit: I've also added a basic role to the client and user (not with any permissions, just the most basic role) but that still hasn't helped. I would expected if this was a role/permissions issue that I'd be getting an unauthorized, though, instead of a 400
.
Edit: It turns out part of my problem was that my user (and problem my client) were not enabled. Enabling both fixed part of the problem. My final problem is that I need the client to be confidential, but I cannot find how to configure this via the Java client API.
Currently I don't know how to configure the access type to be confidential with the Java client.