【发布时间】:2021-06-21 17:44:17
【问题描述】:
使用Java 中的keycloak-admin-client,我成功地创建了一个新客户端和一个新用户。但是,我似乎无法使用用户为客户端获取 JWT。
这是我的代码:
// 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());
这给了我一个javax.ws.rs.BadRequestException: HTTP 400 Bad Request,但不幸的是,我似乎找不到比这更有帮助的东西了。我已经调试过,但无法辨别任何可以告诉我我的请求到底有什么问题的消息。
我还尝试从创建客户端并将其传递给第二个 Keycloak 实例中删除客户端密码,但我仍然得到400。
编辑:我已尝试查看日志(我在 Docker 容器中运行 Keycloak),但出现此问题时似乎没有记录任何内容。
编辑:我还为客户和用户添加了一个基本角色(没有任何权限,只是最基本的角色),但这仍然没有帮助。我希望这是一个角色/权限问题,但我会得到未经授权的,而不是400。
编辑:原来我的部分问题是我的用户(和我的客户的问题)没有启用。启用两个固定部分的问题。我的最后一个问题是我需要客户端保密,但我找不到如何通过 Java 客户端 API 进行配置。
【问题讨论】:
-
.grantType(OAuth2Constants.PASSWORD)听起来您想使用直接访问授权流程,但我在您的test-client(clientRep) 中看不到允许该流程。 -
好建议,但我试过了,但不幸的是我仍然收到
400。我以后可能还需要它,所以我会保留它以防万一。 -
stackoverflow.com/questions/63721080/… 我发现了这个,我猜我可能需要创建一个新领域。如果我理解链接答案的问题,您将无法从
master领域获得 JWT。 -
我尝试使用
master以外的其他领域,并且有一个短暂的时刻我认为我走在正确的轨道上,但我错了,我仍然得到400。是否出于同样的原因我不确定,但我会尽快更新我的代码 sn-p 以反映我目前所拥有的。 -
在创建领域时,您可以设置以下内容:\
realmRep.eventsEnabled(true);realmRep.setEnabledEventTypes(List.of("LOGIN_ERROR","CODE_TO_TOKEN_ERROR","CLIENT_LOGIN_ERROR"));realmRep.setEventsExpiration(172800);也许在管理 GUI 中会弹出一些事件来帮助您。
标签: java jboss jwt keycloak keycloak-services