0

Java的Active Directory 身份验证库(ADAL4J) 允许使用以下(简化的)代码通过访问令牌对Microsoft Graph API进行身份验证:

public String authenticate(String authorizationUrl, String clientId, String clientSecret) throws Exception {
    ExecutorService service = Executors.newFixedThreadPool(1);
    AuthenticationContext context = new AuthenticationContext(authorizationUrl, false, service);
    ClientCredential credential = new ClientCredential(clientId, clientSecret);
    Future<AuthenticationResult> future = context.acquireToken(“https://graph.microsoft.com”, credential, null);
    return future.get().getAccessToken();
}

以上适用于 Graph 的某些部分(例如,用于访问Office 365帐户),但不适用于OneDrive,它返回没有适当授权的访问令牌。

通过POSTMAN获取访问令牌按预期工作,具有以下参数:

authorizationUrl: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
accessTokenUrl: https://login.microsoftonline.com/common/oauth2/v2.0/token
clientId: <the clientId for the application>
clientSecret: <the clientSecret for the application> 
scope: https://graph.microsoft.com/.default
state: <empty>

更具体地说,在POSTMAN中运行上述命令会返回一个具有附加范围的访问令牌,包括https://graph.microsoft.com/Files.ReadWrite.All. Java在调用上述方法的应用程序中使用该访问令牌确实有效,例如,它列出了用作 REST 路径authenticate()的根目录的内容。/me/drive/root/children

但是,如果使用该authenticate()方法返回的访问令牌,则会返回错误OneDriveme如果使用特定租户 ID 而不是common在 authorizationUrl 中,则从路径中删除用户名 ( ) 仅返回 1 个文件名。

似乎没有办法在其中添加范围值,ADAL4J并且许多其他变体要么导致错误,要么导致返回 1 个文件(可能来自不同的上下文)。

有没有办法通过 ADAL4J 为 OneDrive 获取完全授权的访问令牌?

4

1 回答 1

1

有两种不同的权限:一种是应用程序权限,另一种是委托权限。

“委托”权限​​使用来自已登录资源所有者的委托授权指定基于范围的访问,在运行时作为客户端访问令牌中的“scp”声明呈现给资源。

“应用程序”权限使用客户端应用程序的凭据/身份指定基于角色的访问,在运行时作为客户端访问令牌中的“角色”声明呈现给资源。

当您第一次从 POSTMAN 获得令牌时,您将被要求提供您的凭据。这样,您将获得一个具有委托权限的令牌,该令牌代表该帐户。这样,您就可以调用 /me 下的 Graph API。

但是,你用来获取token的java代码只能获取应用权限的访问token。该应用程序没有用户身份,因此在调用 /me 下的 Graph API 时会出错。使用应用程序权限,您只能以 /users/{user-id} 的身份调用 Graph API

解决方案:

您可以在 Java 中获得具有委派权限的访问令牌,如下所示:

A) 创建一个具有公共客户端平台的应用程序

在此处输入图像描述

B) 添加必要的 Graph API 权限,并为您的租户授予管理员同意

在此处输入图像描述

C) 获取令牌

ExecutorService service = Executors.newFixedThreadPool(1);
AuthenticationContext context = null;
try {
    context = new AuthenticationContext("https://login.microsoftonline.com/" + "TENANT_ID", false, service);
    Future<AuthenticationResult> future = context.acquireToken("https://graph.microsoft.com", "client_id", "username", "password",null);
    System.out.println( future.get().getAccessToken());
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
} catch (MalformedURLException e) {
    e.printStackTrace();
}finally {
    service.shutdown();
}
于 2019-08-02T06:35:58.400 回答