You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用gocloak中Login()返回的Access Token无法在Keycloak创建新Client的原因排查

Why does gocloak.Login() return an access token that fails to create a Keycloak Client (403 Forbidden)?

这是因为gocloak.Login()gocloak.LoginAdmin()获取的Access Token权限完全不同,前者的权限不足以执行创建Client的操作,后者拥有管理员级别的权限,具体差异如下:

1. 两个登录方法的身份本质不同

  • gocloak.Login()采用的是客户端凭证流(Client Credentials Flow):你传入的"my-go-service"是一个Keycloak客户端ID,"vizhhp0qnDGaiq4k0aOzzn4RaaqSwU2b"是这个客户端的密钥,它代表的是客户端本身的身份,而不是一个具备管理权限的用户。
  • gocloak.LoginAdmin()采用的是密码流(Password Flow):你传入的"admin"是Keycloak的管理员用户账号,获取的Token代表的是管理员用户身份,默认拥有对Realm的全量管理权限。

2. Keycloak的权限控制逻辑限制

创建Client属于Realm级别的管理操作,需要对应的权限(比如manage-clients角色):

  • Login()获取的Token,默认情况下"my-go-service"这个客户端并没有被授予demorealm的管理权限,所以Keycloak会拒绝这个操作,返回403 Forbidden。
  • LoginAdmin()获取的Token,管理员用户默认拥有Realm的所有管理权限,包括创建Client的权限,因此可以成功执行操作。

如果你想通过Login()实现创建Client的操作

如果确实需要用客户端身份来执行这个管理操作,可以按照以下步骤配置:

  • 在Keycloak控制台中,进入master Realm(你的my-go-service客户端所在的Realm),找到这个客户端。
  • 开启Service Accounts Enabled选项,然后切换到「Service Account Roles」标签页。
  • 在「Client Roles」下拉框中选择demorealm,然后将manage-clients等必要的管理角色添加到这个客户端的服务账户中。
  • 确保客户端的Access Type设置为confidential(因为需要使用密钥进行凭证登录)。

你的代码示例

func main() {
    newClientID := "new_client"
    client := gocloak.NewClient("http://localhost:8080")
    // Login()返回的Access Token导致403错误
    jwt, _ := client.Login(context.Background(), "my-go-service", "vizhhp0qnDGaiq4k0aOzzn4RaaqSwU2b", "master", "admin", "Pa55w0rd")
    _, err := client.CreateClient(context.Background(), jwt.AccessToken, "demorealm", gocloak.Client{
        ClientID: &newClientID})
    if err != nil {
        fmt.Println(err.Error())
    }
    // LoginAdmin()返回的Access Token可正常工作
    jwt, _ = client.LoginAdmin(context.Background(), "admin", "Pa55w0rd", "master")
    clientID, err := client.CreateClient(context.Background(), jwt.AccessToken, "demorealm", gocloak.Client{
        ClientID: &newClientID})
    if err != nil {
        fmt.Println(err.Error())
    } else {
        fmt.Printf("Client %s created", clientID)
    }
}

执行结果

403 Forbidden: unknown_error
Client d869fd8d-e5f0-4567-99de-69ccc4403705 created

内容的提问来源于stack exchange,提问作者Lương Nguyễn Trọng Duc

火山引擎 最新活动