Keycloak管理员客户端对尝试列出领域的响应为”Bad Request”。

huangapple go评论72阅读模式
英文:

Keycloak admin client responds with Bad Request to attempt to list realms

问题

我正试图对一个新的Keycloak实例进行健康性简单测试(恰好是运行在Docker容器中的),通过尝试使用Java管理员客户端以管理员用户身份列出实例。但由于客户端在尝试获取访问令牌时出错,这一操作一直失败,错误信息为HTTP 400 Bad Request。我应该如何配置Keycloak或管理员客户端来执行这个简单的查询?

失败的堆栈跟踪如下:

java.lang.AssertionError: Able to list realms
	at [MyClass].listRealms([MyClass].java:69)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	[junit stack-trace]
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)
	[jax-rs stack-trace]
	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)
	[jax-rs stack-trace]

执行查询的关键代码如下:

   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()));
      }
   }

创建Keycloak实例的代码如下:

   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);
   }

这个测试失败发生在Eclipse中运行测试时。但是在使用Maven运行测试时(即使用maven-failsafe-plugin),也会出现相同的问题。

相同的错误模式(HTTP 400 Bad Request)也会发生在以下情况下:

  • 使用不存在的客户端ID,而不是使用null客户端ID(在这种情况下,我期望会出现HTTP 404 Not Found
  • 使用错误的密码(在这种情况下,我期望会出现HTTP 401 UnauthorizedHTTP 403 Forbidden

我正在使用的URL似乎是正确的,因为如果我故意使用不正确的URL路径,我会得到预期的HTTP 404 Not Found错误模式,如果我故意使用不正确的主机名,我会得到预期的UnknownHostException错误。

这个问题在Keycloak版本11.0.2(撰写本文时的当前版本)中出现,也在版本11.0.0中出现过。

英文:

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&lt;RealmRepresentation&gt; realms;
         try {
            realms = keycloak.realms().findAll();
         } catch (final Exception e) {// provide better diagnostics
            throw new AssertionError(&quot;Able to list realms&quot;, e);
         }
         assertThat(realms, not(empty()));
      }
   }

with the Keycloak instance created thus:

   private static final String ADMIN_USER = &quot;admin&quot;;
   private static final String ADMIN_PASSWORD = &quot;letmein&quot;;
   private static final String ADMIN_REALM = &quot;master&quot;;
   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.

答案1

得分: 2

尽管Keycloak会自动创建一个名为master的realm,并带有一些客户端ID,您可以自动设置一个管理员用户,但似乎您不能在Java管理员客户端中使用它们。相反,您必须创建(或导入)一个realm和客户端ID,然后在创建Keycloak实例时指定。然后,Keycloak将不会对Bad Request报错。

英文:

Although Keycloak automatically creates a master realm, with several client IDs, and you can automate setting up an admin user, its seems you can not use those with the Java admin client. You must instead create (or import) a realm and client ID, which you can then indicate when you create the Keycloak instance. Keycloak will not then complain about a Bad Request.

huangapple
  • 本文由 发表于 2020年9月3日 17:50:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/63721080.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定