使用 Keycloak 颁发“API 密钥”

问题描述 投票:0回答:2

我的设置由三个部分组成:

  • 后端应用程序(Python/Flask)
  • 前端应用程序(VueJS)
  • 钥匙斗篷

前端将使用 Keycloak 让用户登录并使用访问令牌来验证对后端的请求。到目前为止,一切都很好。

现在我希望第三方应用程序能够向后端发出经过身份验证的请求,我想知道如何使用 Keycloak 来实现这一点?我的想法是为每个客户颁发一组新的凭据。然后,他们的应用程序与 Keycloak 通信以获取访问令牌。然后我可以使用 Keycloak 来管理 API 所有用户的访问控制。

  • 第 3 方应用程序如何在 Keycloak - 客户端中表示?用户? ...?
  • 这种用例有最佳实践吗?
authentication oauth authorization keycloak
2个回答
67
投票

我终于找到了一个运行良好的解决方案,似乎是向外部应用程序颁发凭证的“Keycloak 方式”。要创建一组新的凭据,请添加新的 Keycloak 客户端并更改以下设置:

  • 标准流程启用:关闭
  • 直接访问补助已启用:关闭
  • 访问类型:机密
  • 服务帐户已启用:ON

外部应用程序将使用我们新创建的客户名称作为

client_id
client_secret
是自动生成的,可以在 Credentials 选项卡下找到。

授予客户访问您的服务的权限

如果您的受 Keycloak 保护的服务配置为检查传入承载令牌的

aud
声明,则需要执行第二步。默认情况下,Keycloak 向您的客户端颁发的 JWT 令牌的受众将设置为您客户的名称,因此它们将被您的服务拒绝。您可以使用 Client Scopes 来修改该行为:

  1. 创建新的客户端范围
  2. 选择“受众模板”
  3. 选择您想要授予外部应用程序访问权限的服务,然后单击“下一步”
  4. 将范围添加到您刚刚创建的客户端(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
  • 通过基本身份验证对请求进行身份验证,使用您的客户端 ID 作为用户,使用您的客户端密码作为密码
  • 在请求正文中设置
    grant_type=client_credentials

0
投票

更新 @Marco Lamina 对 Keycloak 26 的回答,因为 UI 从那时起已经发生了变化。

1 - 创建客户端

一般

客户类型:

OpenID Connect

能力配置

客户端身份验证:

On

授权:

On

标准流程:

Off

隐式流程:
Off

OAuth 2.0 设备授权:
Off

OIDC CIBA 补助金:
Off

直接访问补助金:
Off

服务帐户角色:
On

登录设置

将一切留空

2 - 配置角色

在您的新客户端上,转到

Service accounts roles
,然后确保分配了必要的角色(我添加了一些
realm-management
角色,因为我希望我的服务帐户能够创建和管理组)。

3 - 检索访问令牌

POST {keycloak-url}/realms/{your-realm}/protocol/openid-connect/token

标题

内容类型:

application/x-www-form-urlencoded

身体

确保正文已进行表单编码。

client_id:

{your-client-id}

客户端秘密:
{your-client-secret}

grant_type:
client_credentials

Javascript 示例

检索令牌。

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}`,
    },
});
© www.soinside.com 2019 - 2024. All rights reserved.