Keycloak:使用新创建的客户端和用户获取 JWT
Posted
技术标签:
【中文标题】Keycloak:使用新创建的客户端和用户获取 JWT【英文标题】:Keycloak: Obtain JWT Using Newly Created Client and User 【发布时间】: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 进行配置。
????目前我不知道如何将访问类型配置为对 Java 客户端保密。
【问题讨论】:
.grantType(OAuth2Constants.PASSWORD)
听起来您想使用直接访问授权流程,但我在您的 test-client
(clientRep
) 中看不到允许该流程。
好建议,但我试过了,但不幸的是我仍然收到400
。我以后可能还需要它,所以我会保留它以防万一。
***.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 中会弹出一些事件来帮助您。
【参考方案1】:
好的,所以我的代码有多个问题。这些是我必须做的所有事情来解决我的问题:
-
我必须创建一个新领域,而不是尝试从默认的
master
领域获取 JWT 访问令牌。
Keycloak admin client responds with Bad Request to attempt to list realms
我的用户/客户端未启用。
clientRep.setEnabled(true);
userRep.setEnabled(true);
我的客户是bearer-only
,它只验证令牌,但不授予它们。
keycloak bearer-only clients: why do they exist?
可以使用public
客户端(默认)或使用clientRep.setPublicClient(false);
将其保密
【讨论】:
以上是关于Keycloak:使用新创建的客户端和用户获取 JWT的主要内容,如果未能解决你的问题,请参考以下文章
Keycloak:使用 keycloak-admin 为用户生成访问令牌
Keycloak 使用不同的客户端重新验证经过身份验证的用户