使用 ADAL4J 的 OneDrive 身份验证

OneDrive authentication using ADAL4J

Active Directory Authentication Library for Java (ADAL4J) allows authentication via access token to the 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,其中 returns 一个访问令牌不有适当的授权。

通过 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 returns 具有其他范围的访问令牌,包括 https://graph.microsoft.com/Files.ReadWrite.All。在调用上述 authenticate() 方法的 Java 应用程序中使用该访问令牌确实有效,例如它使用 /me/drive/root/children 作为 REST 路径列出根目录的内容。

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

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

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

有两种不同的权限:一种是申请权限,另一种是委派权限。

"Delegated" 权限使用已登录资源所有者的委派授权指定基于范围的访问,在 运行 时作为 "scp" 在客户端的访问令牌中声明。

"Application" 权限使用客户端应用程序的 credentials/identity 指定基于角色的访问,在 运行 时作为 [=46] 提供给资源=] 在客户端的访问令牌中声明。

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

但是,您用来获取token的java代码只能获取到application权限的access token。该应用程序没有用户身份,因此在调用 /me 下的 Graph API 时会出错。有应用程序权限,您只能调用图形 API 作为 /users/{user-id}

解法:

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

A) 使用 public 客户端平台

创建应用

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();
}