Java调用Duo Security Admin API返回401错误,请求排查问题
Duo Security Admin API 401错误原因与修复方案
核心错误:认证方式不正确
你当前使用的Basic Auth(Base64编码密钥对)并非Duo Admin API要求的认证方式,Duo API需要基于HMAC-SHA1签名的自定义Authorization头,这是导致401未授权错误的根本原因。
错误细节说明
Duo Admin API的认证规则明确要求:
- 禁止使用Basic Auth,必须生成HMAC-SHA1签名验证请求合法性
- 签名需结合HTTP方法、请求路径、Date头、API主机名参数,用你的secretKey加密
- Authorization头格式为:
Duo <integrationKey>:<base64EncodedSignature>
修正后的Java代码
void users() { // Duo Admin API credentials and API hostname String integrationKey = "DI7ABPU9TUJQO14RET9Q"; String secretKey = "YzDs7ZeQGMllravxDQxcn4jNAwyqF42P1XBDdGd2"; String apiHostname = "api-d221a358.duosecurity.com"; try { String usersPath = "/admin/v1/users"; String usersUrl = "https://" + apiHostname + usersPath; URL url = new URL(usersUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); // 生成符合RFC 1123格式的Date头 String dateHeader = OffsetDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME); connection.setRequestProperty("Date", dateHeader); connection.setRequestProperty("Content-Type", "application/json"); // 生成Duo要求的HMAC-SHA1签名 String signature = generateDuoSignature("GET", usersPath, dateHeader, apiHostname, secretKey); connection.setRequestProperty("Authorization", "Duo " + integrationKey + ":" + signature); int responseCode = connection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { String inputLine; StringBuilder response = new StringBuilder(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } System.out.println("List of Users: " + response.toString()); } } else { System.out.println("Get Users request failed with HTTP response code: " + responseCode); // 读取错误响应详情辅助排查 try (BufferedReader errIn = new BufferedReader(new InputStreamReader(connection.getErrorStream()))) { String inputLine; StringBuilder errResponse = new StringBuilder(); while ((inputLine = errIn.readLine()) != null) { errResponse.append(inputLine); } System.out.println("Error details: " + errResponse.toString()); } } connection.disconnect(); } catch (Exception e) { e.printStackTrace(); } } // 生成Duo API所需的HMAC-SHA1签名 private static String generateDuoSignature(String method, String path, String date, String host, String secretKey) throws NoSuchAlgorithmException, InvalidKeyException { // 拼接签名原始字符串:方法\n路径\n日期\n主机\n(POST请求需追加body内容,GET留空) String signatureString = String.join("\n", method, path, date, host, ""); // 使用secretKey作为密钥执行HMAC-SHA1加密 Mac mac = Mac.getInstance("HmacSHA1"); mac.init(new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1")); byte[] hashBytes = mac.doFinal(signatureString.getBytes(StandardCharsets.UTF_8)); // 加密结果Base64编码 return Base64.getEncoder().encodeToString(hashBytes); }
额外注意事项
- 确保本地服务器时间与Duo服务器时间差在15分钟内,否则签名正确也会返回401
- 核对integrationKey和secretKey的准确性,确认该集成具备访问
/admin/v1/users接口的权限 - 若为POST请求,签名字符串末尾需追加请求body的内容
内容的提问来源于stack exchange,提问作者Enamul Haque
相关产品推荐
相关产品推荐

