如何用Keycloak Admin Client 24.0.0开启客户端认证与授权?
我使用org.keycloak:keycloak-admin-client:24.0.0在Keycloak 24.0.0上通过代码创建领域和客户端,需要开启Client authentication和Authorization功能。
先创建客户端,再用以下代码更新配置:
ClientRepresentation clientRepresentation = getClientRepresentation(realm); ClientResource clientResource = getClientResource(realm, clientRepresentation); clientRepresentation.setAuthorizationServicesEnabled(true); clientRepresentation.setStandardFlowEnabled(true); clientRepresentation.setDirectAccessGrantsEnabled(true); clientRepresentation.setPublicClient(true); clientRepresentation.setEnabled(true); clientRepresentation.setServiceAccountsEnabled(true); clientRepresentation.setAlwaysDisplayInConsole(true); clientRepresentation.setAttributes(Map.of( "oauth2.device.authorization.grant.enabled", "false", "oidc.ciba.grant.enabled", "false", "login_theme", "base", "display.on.consent.screen", "false", "backchannel.logout.url", "", "backchannel.logout.session.required", "true", "backchannel.logout.revoke.offline.tokens", "false" )); clientRepresentation.setRedirectUris(List.of(publicUrl + "/*")); clientResource.update(clientRepresentation);
调试时看到发送的PUT请求体如下:
{ "id": "de890c6a-7695-4cce-b512-87989059860c", "clientId": "my-client", "name": "my-client", "description": null, "rootUrl": null, "adminUrl": null, "baseUrl": null, "surrogateAuthRequired": false, "enabled": true, "alwaysDisplayInConsole": true, "clientAuthenticatorType": "client-secret", "secret": null, "registrationAccessToken": null, "defaultRoles": null, "redirectUris": [ "http://localhost:8080/*" ], "webOrigins": [], "notBefore": 0, "bearerOnly": false, "consentRequired": false, "standardFlowEnabled": true, "implicitFlowEnabled": false, "directAccessGrantsEnabled": true, "serviceAccountsEnabled": true, "authorizationServicesEnabled": true, "directGrantsOnly": null, "publicClient": true, "frontchannelLogout": false, "protocol": "openid-connect", "attributes": { "oidc.ciba.grant.enabled": "false", "client.secret.creation.time": "1709725705", "backchannel.logout.session.required": "true", "login_theme": "base", "display.on.consent.screen": "false", "oauth2.device.authorization.grant.enabled": "false", "backchannel.logout.revoke.offline.tokens": "false" }, "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": true, "nodeReRegistrationTimeout": -1, "registeredNodes": null, "protocolMappers": [ { "id": "a939828f-f524-4d06-aacf-490ea0e2e105", "name": "Client IP Address", "protocol": "openid-connect", "protocolMapper": "oidc-usersessionmodel-note-mapper", "consentRequired": false, "consentText": null, "config": { "user.session.note": "clientAddress", "introspection.token.claim": "true", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "clientAddress", "jsonType.label": "String" } }, { "id": "b62609d1-330f-445e-ab73-edf78b16f396", "name": "Client ID", "protocol": "openid-connect", "protocolMapper": "oidc-usersessionmodel-note-mapper", "consentRequired": false, "consentText": null, "config": { "user.session.note": "client_id", "introspection.token.claim": "true", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "client_id", "jsonType.label": "String" } }, { "id": "1d78e050-38eb-4da5-950e-fe5112471ddf", "name": "Client Host", "protocol": "openid-connect", "protocolMapper": "oidc-usersessionmodel-note-mapper", "consentRequired": false, "consentText": null, "config": { "user.session.note": "clientHost", "introspection.token.claim": "true", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "clientHost", "jsonType.label": "String" } } ], "clientTemplate": null, "useTemplateConfig": null, "useTemplateScope": null, "useTemplateMappers": null, "defaultClientScopes": [ "web-origins", "acr", "roles", "profile", "email" ], "optionalClientScopes": [ "address", "phone", "offline_access", "microprofile-jwt" ], "authorizationSettings": null, "access": { "view": true, "configure": true, "manage": true }, "origin": null }
请求体中已包含"authorizationServicesEnabled": true,但管理控制台客户端设置页的Capability Config部分,Authorization功能仍未开启;且开启两个开关后会出现Credentials标签(包含Client Id and Secret认证器及密钥),但代码操作后没有该标签。对比UI创建相同设置客户端的请求payload,发现与上述一致,不清楚问题所在。
问题:如何通过代码复现在UI中开启Client authentication和Authorization两个开关的操作?
解决方案
1. 修正客户端认证(Client authentication)的配置
你当前设置了publicClient = true,这会将客户端标记为公开客户端,而公开客户端默认不启用客户端认证(对应UI的Client authentication开关关闭)。要开启该开关,需要:
- 将
publicClient设置为false - 确保
clientAuthenticatorType设置为client-secret(默认值,显式指定更清晰)
2. 确保Authorization功能正确生效
仅设置authorizationServicesEnabled = true可能不足以让UI显示开启状态,Keycloak需要初始化授权设置才能激活UI开关并显示Authorization标签页,可通过两种方式处理:
方式一:创建客户端时直接初始化授权设置
在ClientRepresentation中添加授权配置对象:
AuthorizationSettingsRepresentation authSettings = new AuthorizationSettingsRepresentation(); clientRepresentation.setAuthorizationSettings(authSettings);
方式二:更新客户端后显式初始化授权配置
更新客户端后单独调用授权设置接口:
AuthorizationSettingsRepresentation authSettings = new AuthorizationSettingsRepresentation(); clientResource.authorization().getSettings().update(authSettings);
3. 完整修正后的代码示例
ClientRepresentation clientRepresentation = getClientRepresentation(realm); ClientResource clientResource = getClientResource(realm, clientRepresentation); // 开启Client authentication:设置为保密客户端 clientRepresentation.setPublicClient(false); clientRepresentation.setClientAuthenticatorType("client-secret"); // 开启Authorization并初始化配置 clientRepresentation.setAuthorizationServicesEnabled(true); AuthorizationSettingsRepresentation authSettings = new AuthorizationSettingsRepresentation(); clientRepresentation.setAuthorizationSettings(authSettings); // 原有配置保留 clientRepresentation.setStandardFlowEnabled(true); clientRepresentation.setDirectAccessGrantsEnabled(true); clientRepresentation.setEnabled(true); clientRepresentation.setServiceAccountsEnabled(true); clientRepresentation.setAlwaysDisplayInConsole(true); clientRepresentation.setAttributes(Map.of( "oauth2.device.authorization.grant.enabled", "false", "oidc.ciba.grant.enabled", "false", "login_theme", "base", "display.on.consent.screen", "false", "backchannel.logout.url", "", "backchannel.logout.session.required", "true", "backchannel.logout.revoke.offline.tokens", "false" )); clientRepresentation.setRedirectUris(List.of(publicUrl + "/*")); // 更新客户端 clientResource.update(clientRepresentation); // 可选:若授权未生效,单独更新授权配置 // clientResource.authorization().getSettings().update(authSettings);
关键说明
- Client authentication开关:仅保密客户端(
publicClient = false)能开启该功能,公开客户端无需密钥认证,因此UI开关默认关闭。 - Authorization开关:必须初始化授权设置(哪怕是默认配置),Keycloak才会在UI中激活该开关并显示Authorization标签页。
- Credentials标签:当客户端为保密类型且认证器为
client-secret时,Keycloak会自动生成客户端密钥,Credentials标签会自动出现。
内容的提问来源于stack exchange,提问作者ndtreviv

