我的设置由三个部分组成:
前端将使用 Keycloak 让用户登录并使用访问令牌来验证对后端的请求。到目前为止,一切都很好。
现在我希望第三方应用程序能够向后端发出经过身份验证的请求,我想知道如何使用 Keycloak 来实现这一点?我的想法是为每个客户颁发一组新的凭据。然后,他们的应用程序与 Keycloak 通信以获取访问令牌。然后我可以使用 Keycloak 来管理 API 所有用户的访问控制。
我终于找到了一个运行良好的解决方案,似乎是向外部应用程序颁发凭证的“Keycloak 方式”。要创建一组新的凭据,请添加新的 Keycloak 客户端并更改以下设置:
外部应用程序将使用我们新创建的客户名称作为
client_id
。 client_secret
是自动生成的,可以在 Credentials 选项卡下找到。
如果您的受 Keycloak 保护的服务配置为检查传入承载令牌的
aud
声明,则需要执行第二步。默认情况下,Keycloak 向您的客户端颁发的 JWT 令牌的受众将设置为您客户的名称,因此它们将被您的服务拒绝。您可以使用 Client Scopes 来修改该行为:
Keycloak 现在会将您的服务名称添加到其向您的新客户端颁发的所有 JWT 令牌的
aud
声明中。请查看 Service Accounts 上的 Keycloak 文档了解更多详细信息。
外部应用程序现在可以使用其凭据从 Keycloak 的令牌端点获取访问令牌:
POST {keycloak-url}/auth/realms/atlas/protocol/openid-connect/token
Content-Type
标题设置为 application/x-www-form-urlencoded
grant_type=client_credentials
更新 @Marco Lamina 对 Keycloak 26 的回答,因为 UI 从那时起已经发生了变化。
客户类型:
OpenID Connect
客户端身份验证:
On
授权:
On
标准流程:
Off
Off
Off
Off
Off
On
将一切留空
在您的新客户端上,转到
Service accounts roles
,然后确保分配了必要的角色(我添加了一些 realm-management
角色,因为我希望我的服务帐户能够创建和管理组)。
POST {keycloak-url}/realms/{your-realm}/protocol/openid-connect/token
内容类型:
application/x-www-form-urlencoded
确保正文已进行表单编码。
client_id:
{your-client-id}
{your-client-secret}
client_credentials
检索令牌。
const keycloakURL = `${keycloakURL}/realms/${keycloakRealm}/protocol/openid-connect/token`;
const response = await fetch(keycloakURL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
client_id: this.client,
client_secret: this.secret,
grant_type: "client_credentials",
}),
});
const accessToken = (await response.json()).access_token;
使用代币。
// Example using https://www.keycloak.org/docs-api/latest/rest-api/index.html
// Make sure your client is granted proper access.
const keycloakURL = `${keycloakURL}/admin/realms/${keycloakRealm}/${keycloakEndpoint}`;
const response = await fetch(keycloakURL, {
body: JSON.stringify({...}),
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
});