使用 Java 从 AAD 访问 MS Graph 用户数据

MS Graph User Data Access from AAD using Java

我正在尝试使用 Java 访问 AAD 帐户的 MS Graph。它是获取所有用户数据。尝试访问 MS Graph 时出现 401 错误:

            ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
                            Collections.singleton("https://graph.microsoft.com/.default"))
                    .build();

            CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);

            URL url = new URL("https://graph.microsoft.com/v1.0/users");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            conn.setRequestMethod("GET");
            conn.setRequestProperty("Authorization", "Bearer " + future.get());
            conn.setRequestProperty("Accept","application/json");

            int httpResponseCode = conn.getResponseCode();
            if(httpResponseCode == HTTPResponse.SC_OK) {

                try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
                    String inputLine;
                    while ((inputLine = in.readLine()) != null) {
                        responseString.append(inputLine);
                    }
                }
            }
          return responseString.toString();

范围和其他权限已授予。 我得到以下结果。希望任何人都可以指导我解决问题。

这是我最新的代码。我使用函数 getAccessTokenByClientCredentialGrant 获取访问令牌,并通过将访问令牌添加到 header 来手动调用 GET api 调用。根据我的知识,使用图形客户端是最佳实践。

            String CLIENT_ID = "{{ClientId}}";
            String CLIENT_SECRET = "{{ClientSecret}}";
            String AUTHORITY = "https://login.microsoftonline.com/{{TenantId}}";
            Set<String> SCOPE = Collections.singleton("https://graph.microsoft.com/.default");
        try {

            String access_token = getAccessTokenByClientCredentialGrant(CLIENT_ID, CLIENT_SECRET,
                    AUTHORITY, SCOPE).accessToken();

            URL url = new URL("https://graph.microsoft.com/v1.0/users");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            conn.setRequestMethod("GET");
            conn.setRequestProperty("Authorization", "Bearer " + access_token);
            conn.setRequestProperty("Accept","application/json");

            int httpResponseCode = conn.getResponseCode();
            JsonPointer responseString = null;
            if(httpResponseCode == HTTPResponse.SC_OK) {

                try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
                    String inputLine;
                    while ((inputLine = in.readLine()) != null) {
                       response.put(RESULT, responseString.toString());
                    }
                }
            }
          
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("Response "+responseString);

getAccessTokenByClientCredentialGrant 函数是这样的:

 private IAuthenticationResult getAccessTokenByClientCredentialGrant(String client_id, String client_secret, String authority, Set<String> scope) throws MalformedURLException, ExecutionException, InterruptedException {
    ConfidentialClientApplication app = ConfidentialClientApplication
            .builder(client_id, ClientCredentialFactory
                    .createFromSecret(client_secret))
            .authority(authority).build();

    ClientCredentialParameters clientCredentialParam = ClientCredentialParameters
            .builder(scope).build();

    CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
    return future.get();
}

建议读物: https://blogs.aaddevsup.xyz/2021/08/microsoft-graph-why-you-cannot-call-the-me-endpoint-with-a-token-acquired-via-the-client-credentials-grant-flow/