I am attempting a simple test of the health of a fresh instance of Keycloak (running in a Docker container, it so happens), by trying to list the realms using the Java admin client as the admin user. But this repeatedly fails due to an HTTP 400 Bad Request, apparently when the client is attempting to get an access token. How must I configure Keycloak, or the admin client, to do this simple query?
The stack-trace of the failure is thus:
java.lang.AssertionError: Able to list realms
at [MyClass].listRealms([MyClass].java:69)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
[junit stack-trace]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: javax.ws.rs.ProcessingException: javax.ws.rs.BadRequestException: HTTP 400 Bad Request
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:603)
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:440)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:149)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
at com.sun.proxy.$Proxy45.findAll(Unknown Source)
at [MyClass].listRealms([MyClass].java:67)
... 67 more
Caused by: javax.ws.rs.BadRequestException: HTTP 400 Bad Request
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.handleErrorStatus(ClientInvocation.java:219)
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.extractResult(ClientInvocation.java:195)
at org.jboss.resteasy.client.jaxrs.internal.proxy.extractors.BodyEntityExtractor.extractEntity(BodyEntityExtractor.java:62)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:151)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
at com.sun.proxy.$Proxy43.grantToken(Unknown Source)
at org.keycloak.admin.client.token.TokenManager.grantToken(TokenManager.java:90)
at org.keycloak.admin.client.token.TokenManager.getAccessToken(TokenManager.java:70)
at org.keycloak.admin.client.token.TokenManager.getAccessTokenString(TokenManager.java:65)
at org.keycloak.admin.client.resource.BearerAuthFilter.filter(BearerAuthFilter.java:52)
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:590)
... 73 more
The crucial code doing the query is this:
public void listRealms() {
try (var keycloak = container.getKeycloakInstance()) {
final List<RealmRepresentation> realms;
try {
realms = keycloak.realms().findAll();
} catch (final Exception e) {// provide better diagnostics
throw new AssertionError("Able to list realms", e);
}
assertThat(realms, not(empty()));
}
}
with the Keycloak
instance created thus:
private static final String ADMIN_USER = "admin";
private static final String ADMIN_PASSWORD = "letmein";
private static final String ADMIN_REALM = "master";
private static final String ADMIN_CLIENT_ID = null;
...
public Keycloak getKeycloakInstance() {
return Keycloak.getInstance(getUri().toASCIIString(), ADMIN_REALM,
ADMIN_USER, ADMIN_PASSWORD, ADMIN_CLIENT_ID);
}
That test failure happens to be when running the test in Eclipse. But the problem also occurs when I run the test using Maven (that is, using the maven-failsafe-plugin
).
The same failure mode (HTTP 400 Bad Request ) also occurs if I
- use a non existent client ID, rather than a null client ID (I would expect HTTP 404 Not Found in that case)
- use the wrong password (I would expect HTTP 401 Unauthorized or HTTP 403 Forbidden in that case)
The URL I am using seems to be correct, because if I deliberately use an incorrect URL path I get the expected HTTP 404 Not Found failure mode, and if I deliberately use an incorrect host name I get the expected UnknownHostException
.
This problem occurs with Key cloak version 11.0.2
(the current version at the time of writing) and also occurred with version 11.0.0
.
admin-cli
client and user with properrealm-management
roles. Also check Keycloak server logs - you may find there more details about reason forHTTP 400 Bad Request
error. – Baca