You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Java代码实现基于Keycloak的Argo Workflows SSO认证?

Keycloak认证Argo Workflows服务调用的Java解决方案

错误原因

token not valid for running mode 是因为你传递的用户登录token,其受众(aud字段)仅匹配Argo UI的客户端ID,但Argo Server在服务调用模式下,要求token的受众必须是服务端专用的客户端ID,或者你的Argo配置未允许用户token用于服务调用。

前置配置调整

  • 在Keycloak中新增一个Confidential类型的客户端(命名如argo-server-service):
    • 启用Client Credentials授权类型
    • 给该客户端分配Argo所需的权限角色(比如admin、workflow-submit等)
  • 更新Argo Server的ConfigMap:
    • 若使用服务专用token,设置server.sso.clientId为这个新客户端ID
    • 若要支持用户上下文token,添加server.sso.audiences配置,同时包含UI客户端ID和服务端客户端ID:
      server.sso.audiences: "argo-ui,argo-server-service"
      

Java代码实现

方式1:Client Credentials模式(服务间调用推荐,无用户上下文)

这种方式用服务端客户端凭证从Keycloak获取专用token,适合后台服务直接调用Argo API:

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ArgoKeycloakAuth {
    // 获取服务专用token
    public static String getArgoServiceToken() throws Exception {
        String keycloakTokenUrl = "https://your-keycloak-domain/auth/realms/your-realm/protocol/openid-connect/token";
        String clientId = "argo-server-service";
        String clientSecret = "your-client-secret";

        HttpClient client = HttpClients.createDefault();
        HttpPost tokenPost = new HttpPost(keycloakTokenUrl);
        tokenPost.setHeader("Content-Type", "application/x-www-form-urlencoded");

        // 构建请求体
        String requestBody = String.format(
            "grant_type=client_credentials&client_id=%s&client_secret=%s",
            clientId, clientSecret
        );
        tokenPost.setEntity(new StringEntity(requestBody));

        HttpResponse response = client.execute(tokenPost);
        String responseStr = EntityUtils.toString(response.getEntity());

        // 解析access_token
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode = mapper.readTree(responseStr);
        return jsonNode.get("access_token").asText();
    }

    // 调用Argo Workflows API示例(提交Workflow)
    public static void submitArgoWorkflow(String argoServerUrl, String workflowJson) throws Exception {
        String serviceToken = getArgoServiceToken();
        HttpClient client = HttpClients.createDefault();
        HttpPost submitPost = new HttpPost(argoServerUrl + "/api/v1/workflows/default/submit");
        
        // 设置认证头和内容类型
        submitPost.setHeader("Authorization", "Bearer " + serviceToken);
        submitPost.setHeader("Content-Type", "application/json");
        submitPost.setEntity(new StringEntity(workflowJson));

        HttpResponse response = client.execute(submitPost);
        // 处理响应
        System.out.println("API响应状态: " + response.getStatusLine());
        System.out.println("响应内容: " + EntityUtils.toString(response.getEntity()));
    }

    public static void main(String[] args) throws Exception {
        // 替换为你的Workflow定义JSON和Argo Server地址
        String workflowDef = "{\"workflow\": {\"apiVersion\": \"argoproj.io/v1alpha1\", \"kind\": \"Workflow\", ...}}";
        submitArgoWorkflow("https://your-argo-server-url", workflowDef);
    }
}

注意:代码依赖Apache HttpClient和Jackson Databind,Maven依赖如下:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.14</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

方式2:传递用户上下文token(需Argo配置支持)

如果需要携带用户身份调用Argo,确保用户token的aud字段包含Argo服务端客户端ID,或已在Argo ConfigMap中配置server.sso.audiences允许用户token,代码示例:

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class ArgoUserAuth {
    // 使用用户token调用Argo API
    public static void callArgoWithUserToken(String argoServerUrl, String userAccessToken, String workflowJson) throws Exception {
        HttpClient client = HttpClients.createDefault();
        HttpPost submitPost = new HttpPost(argoServerUrl + "/api/v1/workflows/default/submit");
        
        submitPost.setHeader("Authorization", "Bearer " + userAccessToken);
        submitPost.setHeader("Content-Type", "application/json");
        submitPost.setEntity(new StringEntity(workflowJson));

        HttpResponse response = client.execute(submitPost);
        // 处理响应
        System.out.println("API响应状态: " + response.getStatusLine());
        System.out.println("响应内容: " + EntityUtils.toString(response.getEntity()));
    }
}

验证步骤

  • 用JWT解析工具检查token,确认aud字段包含Argo Server配置的客户端ID
  • 测试API调用,确保返回2xx状态码

内容的提问来源于stack exchange,提问作者Yashwanthkumar Ht

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 05:25:16